diff --git a/tokio/src/fs/file.rs b/tokio/src/fs/file.rs index 2c38e8059f5..d513beb05a4 100644 --- a/tokio/src/fs/file.rs +++ b/tokio/src/fs/file.rs @@ -565,29 +565,30 @@ impl AsyncSeek for File { let me = self.get_mut(); let inner = me.inner.get_mut(); - loop { - match inner.state { - Busy(_) => panic!("must wait for poll_complete before calling start_seek"), - Idle(ref mut buf_cell) => { - let mut buf = buf_cell.take().unwrap(); - - // Factor in any unread data from the buf - if !buf.is_empty() { - let n = buf.discard_read(); - - if let SeekFrom::Current(ref mut offset) = pos { - *offset += n; - } + match inner.state { + Busy(_) => Err(io::Error::new( + io::ErrorKind::Other, + "other file operation is pending, call poll_complete before start_seek", + )), + Idle(ref mut buf_cell) => { + let mut buf = buf_cell.take().unwrap(); + + // Factor in any unread data from the buf + if !buf.is_empty() { + let n = buf.discard_read(); + + if let SeekFrom::Current(ref mut offset) = pos { + *offset += n; } + } - let std = me.std.clone(); + let std = me.std.clone(); - inner.state = Busy(spawn_blocking(move || { - let res = (&*std).seek(pos); - (Operation::Seek(res), buf) - })); - return Ok(()); - } + inner.state = Busy(spawn_blocking(move || { + let res = (&*std).seek(pos); + (Operation::Seek(res), buf) + })); + Ok(()) } } } diff --git a/tokio/src/fs/file/tests.rs b/tokio/src/fs/file/tests.rs index 18a4c078599..1c90a8d1541 100644 --- a/tokio/src/fs/file/tests.rs +++ b/tokio/src/fs/file/tests.rs @@ -955,3 +955,24 @@ fn partial_read_set_len_ok() { assert_eq!(n, FOO.len()); assert_eq!(&buf[..n], FOO); } + +#[test] +fn busy_file_seek_error() { + let mut file = MockFile::default(); + let mut seq = Sequence::new(); + file.expect_inner_write() + .once() + .in_sequence(&mut seq) + .returning(|_| Err(io::ErrorKind::Other.into())); + + let mut file = crate::io::BufReader::new(File::from_std(file)); + { + let mut t = task::spawn(file.write(HELLO)); + assert_ready_ok!(t.poll()); + } + + pool::run_one(); + + let mut t = task::spawn(file.seek(SeekFrom::Start(0))); + assert_ready_err!(t.poll()); +}