Skip to content

Stack overflow in compat layers #1283

@Nemo157

Description

@Nemo157

Minimal repro for futures 0.3.0-alpha.7 provided by @andreasots (https://gist.github.com/andreasots/4ea3982036ad703158ee3ddc11376eee):

#![feature(await_macro, async_await, futures_api)]

use tokio::timer::Delay;
use std::time::Instant;
use futures::prelude::*;
use futures::compat::Future01CompatExt;

fn main() {
    let f = async {
        await!(Delay::new(Instant::now()).compat());
    };
    tokio::run(f.unit_error().boxed().compat());
}

Slightly snipped stack trace (can probably have more unnecessary lines removed):

#42 0x000055555556d669 in <futures_util::compat::compat03to01::CurrentRef as core::task::wake::UnsafeWake>::clone_raw (self=0x1)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat03to01.rs:98
#43 0x000055555556d87a in <core::task::wake::Waker as core::clone::Clone>::clone (self=0x7ffff63fce48) at libcore/task/wake.rs:72
#44 0x000055555556d563 in futures_util::compat::compat01to03::<impl core::convert::From<futures_util::compat::compat01to03::WakerToHandle<'a>> for futures::task_impl::NotifyHandle>::from (handle=...)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat01to03.rs:61
#45 0x000055555556cc23 in <T as core::convert::Into<U>>::into (self=...) at libcore/convert.rs:456
#46 0x00005555555682c8 in futures::task_impl::with_notify::{{closure}}::{{closure}} () at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:497
#47 0x00005555556544db in futures::task_impl::core::BorrowedUnpark::to_owned (self=0x7ffff62012a8) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/core.rs:49
#48 0x000055555564f231 in futures::task_impl::std::BorrowedUnpark::to_owned (self=0x7ffff63fc988) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/std/mod.rs:124
[...]
#20649 0x0000555555652f2f in futures::task_impl::current::{{closure}} (borrowed=0x7ffff63fc980) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:116
#20650 0x0000555555652eaa in futures::task_impl::with (f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:45
#20651 0x0000555555652ef1 in futures::task_impl::current () at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:115
#20652 0x000055555556d669 in <futures_util::compat::compat03to01::CurrentRef as core::task::wake::UnsafeWake>::clone_raw (self=0x1)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat03to01.rs:98
#20653 0x000055555556d87a in <core::task::wake::Waker as core::clone::Clone>::clone (self=0x7ffff63fce48) at libcore/task/wake.rs:72
#20654 0x000055555556d563 in futures_util::compat::compat01to03::<impl core::convert::From<futures_util::compat::compat01to03::WakerToHandle<'a>> for futures::task_impl::NotifyHandle>::from (handle=...)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat01to03.rs:61
#20655 0x000055555556cc23 in <T as core::convert::Into<U>>::into (self=...) at libcore/convert.rs:456
#20656 0x00005555555682c8 in futures::task_impl::with_notify::{{closure}}::{{closure}} () at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:497
#20657 0x00005555556544db in futures::task_impl::core::BorrowedUnpark::to_owned (self=0x7ffff63fc5d8) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/core.rs:49
#20658 0x000055555564f231 in futures::task_impl::std::BorrowedUnpark::to_owned (self=0x7ffff63fc988) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/std/mod.rs:124
#20659 0x0000555555652f2f in futures::task_impl::current::{{closure}} (borrowed=0x7ffff63fc980) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:116
[...]
#20666 0x0000555555569cfb in futures_util::compat::compat01to03::<impl core::future::future::Future for futures_util::compat::compat::Compat<Fut>>::poll::{{closure}} ()
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat01to03.rs:26
#20667 0x000055555556b6cc in futures::task_impl::std::set (task=0x7ffff63fc980, f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/std/mod.rs:78
#20668 0x0000555555568247 in futures::task_impl::with_notify::{{closure}} (task=0x7ffff63fcfe0) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:505
#20669 0x00005555555683b8 in futures::task_impl::with (f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:45
#20670 0x000055555556817b in futures::task_impl::with_notify (notify=0x7ffff63fcad8, id=0, f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:496
#20671 0x000055555556aa8e in futures_util::compat::compat01to03::<impl core::future::future::Future for futures_util::compat::compat::Compat<Fut>>::poll (self=..., lw=0x7ffff63fce48)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat01to03.rs:25
[...]
#20682 0x0000555555569ab1 in futures_util::compat::compat03to01::<impl futures::future::Future for futures_util::compat::compat::Compat<Fut>>::poll::{{closure}} (inner=..., lw=0x7ffff63fce48)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat03to01.rs:21
#20683 0x0000555555569c4c in futures_util::compat::compat03to01::with_context (compat=0x7ffff6a21088, f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat03to01.rs:122
#20684 0x000055555556aab3 in futures_util::compat::compat03to01::<impl futures::future::Future for futures_util::compat::compat::Compat<Fut>>::poll (self=0x7ffff6a21088)
    at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.7/src/compat/compat03to01.rs:21
#20685 0x0000555555651205 in <alloc::boxed::Box<F> as futures::future::Future>::poll (self=0x7ffff6a540c8) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/future/mod.rs:113
#20686 0x00005555555eef13 in <futures::task_impl::Spawn<T>>::poll_future_notify::{{closure}} (f=0x7ffff6a540c8) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:314
#20687 0x00005555555ef1d0 in <futures::task_impl::Spawn<T>>::enter::{{closure}} () at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:388
#20688 0x00005555555da34c in futures::task_impl::std::set (task=0x7ffff63fcfe0, f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/std/mod.rs:78
#20689 0x00005555555ef04b in <futures::task_impl::Spawn<T>>::enter (self=0x7ffff6a540a0, unpark=..., f=...) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:388
#20690 0x00005555555eee7a in <futures::task_impl::Spawn<T>>::poll_future_notify (self=0x7ffff6a540a0, notify=0x7ffff63fd9e8, id=140737331413120) at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/futures-0.1.24/src/task_impl/mod.rs:314
#20691 0x00005555555cd065 in tokio_threadpool::task::Task::run::{{closure}} () at /home/andreas/.cargo/registry/src/git.colasdn.top-1ecc6299db9ec823/tokio-threadpool-0.1.7/src/task/mod.rs:127

The issue appears to be because CurrentRef delays getting the task until it's needed it waits too long and the task's waker has already been replaced with a NotifyWaker that tries to use the CurrentRef, making a loop. Removing CurrentRef and producing a CurrentOwned straight away when needed fixes it. I assume CurentRef is there because CurrentOwned can be expensive with the Arc and accessing task::current, maybe there's an alternative optimization that could be done and will be safe against task::current being changed under it?

cc @seanmonstar since you introduced CurrentRef

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions