NVIDIA/stdexec

nvexec `let_value` et al assumes sender returned from lambda is a stream sender

ericniebler opened this issue · 0 comments

nvexec's customization of let_value calls the lambda and constructs the result sender in temporary storage (good), but it unconditionally attaches a propagate_receiver_t. If that sender is not a stream sender, and if it completes with reference(s) to objects in host memory (say, if it passes to propagate_receiver_t's set_value references to temporaries that live on the host caller's stack, then when device code accesses the values, the process will crash because host memory is inaccessible.

E.g., this crashes:

nvexec::stream_context ctx;

auto snd = stdexec::schedule( ctx.get_scheduler() )
         | stdexec::let_value( [] {
             // this sender will complete with an rvalue reference to
             // an integer in host memory:
             return stdexec::just() | stdexec::then( [] { return 42; } );
           })
           // This sender's receiver, wrapped in `propagate_receiver_t`,
           // will accept the reference to host memory and pass it into
           // a kernel that calls this lambda, causing an access violation.
         | stdexec::then( [] (int i) { ... } );

stdexec::sync_wait( std::move(snd) );

The stream scheduler's let_value customization must assume, if the result sender is not a stream sender, that any values/errors it may complete with are kept in host memory and defensively copy them into device memory.