The program below should not segfault when I only write 'safe' code.
The program below segfaults.
Change the MessageBody trait to take a Pin<&mut self> instead of a &mut self.
Run the following code in debug mode.
use futures::task::{noop_waker, Context};
use futures::stream::once;
use actix_http::body::{MessageBody, BodyStream};
use bytes::Bytes;
fn main() {
let (sender, receiver) = futures::channel::oneshot::channel();
let mut body_stream = Ok(BodyStream::new(once(async {
let x = Box::new(0);
let y = &x;
receiver.await.unwrap();
let z = **y;
Ok::<_, ()>(Bytes::new())
})));
let waker = noop_waker();
let mut context = Context::from_waker(&waker);
let _ = body_stream.as_mut().unwrap().poll_next(&mut context);
sender.send(()).unwrap();
let _ = std::mem::replace(&mut body_stream, Err([0; 32])).unwrap().poll_next(&mut context);
}
I found this problem by searching for 'unsafe' in the actix-web repo.
rustc -V): rustc 1.41.0-nightlyConfirmed the test is crashing test runner.
Provided possible fix will be massive and break actix-web back compatibility as MessageBody trait is used in actix-http, awc and actix-web crates. Is there any other solution?
I dunno atm. But it feels that we will have to refactor all the poll-like methods to accept Pin<&mut Self> eventually, one way or another. It's to hard to control and keep in mind all the &mut self<->Pin<&mut Self> bridges with their invariants/tradeoffs. Even more, future contributions will definitely break the invariants, accidentally and quite often. Here the type system should do its job.
I found a similar issue in actix-codec, if you are going to make a breaking change here then you will probably need one there as well.
Would this be a 2.x release though if we decide to do this?
Should we refactor and shoot for a 3.0 transition for this? I think 2+ has been a good halfway point but I really want to make async/await first order if possible soon.
IMO we _should_ refactor these unsafe's and shoot for a 3.0 release with a reasonably long alpha/beta period.
I think that's the best path forward as well now that Future is stable but it'll be hard to "backport" any new work. We most likely wouldn't be able to work on 2+ changes and 3.0 release simultaneously.
Most helpful comment
I dunno atm. But it feels that we will have to refactor all the poll-like methods to accept
Pin<&mut Self>eventually, one way or another. It's to hard to control and keep in mind all the&mut self<->Pin<&mut Self>bridges with their invariants/tradeoffs. Even more, future contributions will definitely break the invariants, accidentally and quite often. Here the type system should do its job.