Skip to content

Ops that co_await in initiate() do not cancel when executable receives a signal #270

@Hyper-AU

Description

@Hyper-AU

Thankyou for your work on this library.

Any op that calls co_await in initiate() does not cancel as the result of a signal handled by co_main.

This appears to affect acceptor::accept(), read()/read_at(), and write()/write_at().

Tested against develop and 1.90.0 tag, on Linux using gcc 14.2.0, -std=c++23.

Simple reproducer:

  #include <boost/cobalt.hpp>
  #include <boost/cobalt/io.hpp>
  #include <iostream>

  using namespace boost;
  
  cobalt::main co_main(int, char *[]) {
  
      std::cout << "Starting co_main\n";
  
      cobalt::io::acceptor acceptor(cobalt::io::endpoint{cobalt::io::tcp_v4, "0.0.0.0", 55555});
      auto [ec, sock] = co_await as_tuple(acceptor.accept());
      if (ec) {
          std::cout << "Error: " << ec.what() << std::endl;
      } else {
          std::cout << "Socket accepted\n";
      }
  
      co_return 0;
  }
  

Run that and try Ctrl-C while it is waiting for a connection: there is no response and the executable needs to be SIGKILLed (or connect to 55555 to make it exit).

I'm still trying to grok the cobalt internals and doco, so I am unsure if this is by design or if there is logic missing in op and/or composite_promise to support forwarding of the main promise's cancellation signal through to the op.

This inability to be cancelled also breaks the recommended timeout approach, eg:

auto result = co_await race(read(stream, buffer), timer.wait()); will not continue until the buffer is full, even if the timer expires first.

Is there a simple workaround I can use, or some other pattern I should be following?

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