Skip to content

async_fn_in_trait: default fn impl calling fn of same trait with default impl doesn't dispatch properly #107528

Closed
@fasterthanlime

Description

@fasterthanlime

cf. https://octodon.social/@fasterthanlime/109785229512000455

Relevant PR: bearcove/loona#74 (comment) (but it's annoying to run - requires Linux, with a recent enough kernel to have io_uring support)

Here's essentially the shape of the problem, I'll try to come up with a MVCE:

#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]

trait WriteOwned {
  async fn writev_all(&self) {
    self.writev();
  }

  async fn writev(&self) {
   self.write();
  }

  async fn write(&self);
}

impl WriteOwned for TcpStream {
  async fn write(&self) {
    // forward to actual impl
  }

  async fn writev(&self) {
    // forward to actual impl
  }
}

When the concrete type is TcpStream, not only does stream.writev_all call WriteOwned::writev (the default impl) instead of <TcpStream as WriteOwned>::writev, it seems to call it with.. the wrong calling convention? Valgrind is very unhappy and the program ends up segfaulting.

Valgrind output:
2023-01-31T18:20:45.691210Z DEBUG hring_bingo_ktls: Connected to httpbingo
WriteOwned::writev_all, calling writev with 13 items
==125831== Use of uninitialised value of size 8
==125831==    at 0x196CB6: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:0)
==125831==    by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831==    by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831==    by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831==    by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831==    by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831==    by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831==    by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831==    by 0x21D819: tokio::runtime::task::harness::poll_future::{{closure}} (harness.rs:476)
==125831==    by 0x2DB032: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (unwind_safe.rs:271)
==125831==    by 0x2C867B: std::panicking::try::do_call (panicking.rs:483)
==125831==    by 0x2C99AA: __rust_try (in /home/amos/bearcove/hring/target/debug/hring-bingo-ktls)
==125831== 
WriteOwned::write_v with 👈 ==125831== Conditional jump or move depends on uninitialised value(s)
==125831==    at 0x52CEF6: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:230)
==125831==    by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831==    by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831==    by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831==    by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831==    by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831==    by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831==    by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831==    by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831==    by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831==    by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831==    by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831== 
==125831== Conditional jump or move depends on uninitialised value(s)
==125831==    at 0x52CFBF: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:249)
==125831==    by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831==    by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831==    by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831==    by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831==    by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831==    by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831==    by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831==    by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831==    by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831==    by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831==    by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831== 
==125831== Conditional jump or move depends on uninitialised value(s)
==125831==    at 0x52CFAB: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:257)
==125831==    by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831==    by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831==    by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831==    by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831==    by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831==    by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831==    by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831==    by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831==    by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831==    by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831==    by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831== 
==125831== Syscall param write(buf) points to uninitialised byte(s)
==125831==    at 0x4A81D94: write (write.c:26)
==125831==    by 0x4FE2FE: <std::io::stdio::StderrLock as std::io::Write>::write_all (fd.rs:152)
==125831==    by 0x4FF5D5: <std::io::Write::write_fmt::Adapter<T> as core::fmt::Write>::write_str (mod.rs:1671)
==125831==    by 0x52CFFD: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:273)
==125831==    by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831==    by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831==    by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831==    by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831==    by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831==    by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831==    by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831==    by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831==  Address 0x1ffeff3187 is on thread 1's stack
==125831==  in frame #3, created by core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:279)
==125831== 
2 buffers 👈

Note that a rustc bug wasn't my first guess here, since there's "mmap a large chunk of memory and use unsafe code to divvy it up" and "pass ownership of buffers to the kernel for io_uring" fuckery going on, but I feel reasonably confident I can come up with a MVCE if someone doesn't beat me to the punch.

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