forgive me. I read "a synchronous call" as "asynchronous call".
Of course the correct way to "cancel" a sync call in linux is to raise a signal, which should cause the socket's read to return with EINTR.
But before I realised my mistake, I wrote this little test to prove that async calls are canclled :) Maybe someone will find it useful...
#include <cstdlib>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using namespace std::literals;
namespace asio = boost::asio;
using protocol = asio::ip::tcp;
void server(protocol::acceptor& acceptor, int child_pid)
{
acceptor.listen();
auto& executor = acceptor.get_io_context();
auto sock = protocol::socket(executor);
auto timer = asio::system_timer(executor);
acceptor.accept(sock);
auto read_handler = [](auto ec, auto...)
{
if (ec)
std::cerr << "read handler error: " << ec.message();
else
std::cerr << "strange - we expected an error";
};
auto timer_handler = [&](auto ec)
{
if (not ec) {
sock.cancel();
}
};
sock.async_read_some(asio::null_buffers(), read_handler);
timer.expires_after(1s);
timer.async_wait(timer_handler);
executor.run();
auto data = "foo"s;
sock.write_some(asio::buffer(data));
int status = 0;
waitpid(child_pid, & status, 0);
}
void client(asio::io_context& executor, protocol::endpoint server_endpoint)
{
protocol::socket sock(executor);
sock.connect(server_endpoint);
auto on_read = [](auto, auto) {};
sock.async_read_some(asio::null_buffers(), on_read);
executor.run();
}
int main() {
auto executor = asio::io_context();
auto acceptor = protocol::acceptor(executor);
acceptor.open(protocol::v4());
acceptor.bind(protocol::endpoint(protocol::v4(), 0));
auto server_endpoint = acceptor.local_endpoint();
executor.notify_fork(asio::io_context::fork_prepare);
int child_pid = fork();
if (child_pid < 0)
{
std::cerr << "fork failed" << std::endl;
std::exit(100);
}
else if (child_pid > 0)
{
executor.notify_fork(asio::io_context::fork_parent);
server(acceptor,child_pid);
}
else
{
executor.notify_fork(asio::io_context::fork_child);
client(executor, server_endpoint);
}
return 0;
}
expected output: