futures::try_join on DmaStreamWriter can cause panic
tontinton opened this issue · comments
Calling poll_write
after it returned Pending
results in crash. This in itself might be ok, but futures::try_join!
triggers this behavior, so we should either fix the bug or at least document that.
This program triggers the crash:
use futures::{try_join, AsyncWriteExt};
use glommio::{
io::{DmaFile, DmaStreamWriterBuilder},
LocalExecutorBuilder, Placement,
};
fn main() {
let builder = LocalExecutorBuilder::new(Placement::Fixed(1));
builder
.spawn(|| async move {
let file1 = DmaFile::create("/tmp/bug1").await.unwrap();
let mut writer1 = DmaStreamWriterBuilder::new(file1)
.with_write_behind(1)
.with_buffer_size(4096)
.build();
let file2 = DmaFile::create("/tmp/bug2").await.unwrap();
let mut writer2 = DmaStreamWriterBuilder::new(file2)
.with_write_behind(1)
.with_buffer_size(4096)
.build();
let buf = [b'A'; 4096];
println!("Writing...");
for _ in 0..100000 {
try_join!(writer1.write_all(&buf), writer2.write_all(&buf)).unwrap(); // Crash here
}
})
.unwrap()
.join()
.unwrap();
println!("No bug!");
}
With the following output:
Writing...
thread 'unnamed-1' panicked at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/io/dma_file_stream.rs:832:9:
assertion failed: self.waker.is_none()
stack backtrace:
0: rust_begin_unwind
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:595:5
1: core::panicking::panic_fmt
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:67:14
2: core::panicking::panic
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:117:5
3: glommio::io::dma_file_stream::DmaStreamWriterState::add_waker
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/io/dma_file_stream.rs:832:9
4: <&glommio::io::dma_file_stream::DmaStreamWriter as futures_io::if_std::AsyncWrite>::poll_write
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/io/dma_file_stream.rs:1369:13
5: <glommio::io::dma_file_stream::DmaStreamWriter as futures_io::if_std::AsyncWrite>::poll_write
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/io/dma_file_stream.rs:1310:9
6: <&mut T as futures_io::if_std::AsyncWrite>::poll_write
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-io-0.3.28/src/lib.rs:381:17
7: <futures_util::io::write_all::WriteAll<W> as core::future::future::Future>::poll
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.28/src/io/write_all.rs:31:28
8: <futures_util::future::maybe_done::MaybeDone<Fut> as core::future::future::Future>::poll
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.28/src/future/maybe_done.rs:95:38
9: glommio_bug::main::{{closure}}::{{closure}}::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.28/src/async_await/join_mod.rs:105:13
10: <futures_util::future::poll_fn::PollFn<F> as core::future::future::Future>::poll
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.28/src/future/poll_fn.rs:56:9
11: glommio_bug::main::{{closure}}::{{closure}}
at ./src/main.rs:24:17
12: glommio::executor::LocalExecutorBuilder::spawn::{{closure}}::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:717:50
13: glommio::executor::LocalExecutor::run::{{closure}}::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1462:49
14: <core::pin::Pin<P> as core::future::future::Future>::poll
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/future/future.rs:125:9
15: glommio::task::raw::RawTask<F,R,S>::run
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/task/raw.rs:470:20
16: glommio::task::task_impl::Task::run
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/task/task_impl.rs:125:22
17: glommio::executor::LocalExecutor::run_one_task_queue
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1382:29
18: glommio::executor::LocalExecutor::run_task_queues
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1333:17
19: glommio::executor::LocalExecutor::run::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1487:27
20: glommio::executor::LocalExecutor::run::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1522:35
21: scoped_tls::ScopedKey<T>::set
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-1.0.1/src/lib.rs:137:9
22: glommio::executor::LocalExecutor::run
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:1522:13
23: glommio::executor::LocalExecutorBuilder::spawn::{{closure}}
at /home/tony/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glommio-0.8.0/src/executor/mod.rs:717:17
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
thread 'main' panicked at src/main.rs:31:10:
called `Result::unwrap()` on an `Err` value: Thread panicked { .. }
stack backtrace:
0: rust_begin_unwind
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:595:5
1: core::panicking::panic_fmt
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:67:14
2: core::result::unwrap_failed
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/result.rs:1652:5
3: core::result::Result<T,E>::unwrap
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/result.rs:1077:23
4: glommio_bug::main
at ./src/main.rs:9:5
5: core::ops::function::FnOnce::call_once
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/ops/function.rs:250:5
One fix I could think of is that when self.waker is not none, simply return Pending again.
I can upload a PR if you are fine with this solution.
Got excited and opened a PR :) #611