chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.85k stars 1.2k forks source link

notify_fork() API not really safe on Linux #1231

Open maciejsszmigiero opened 1 year ago

maciejsszmigiero commented 1 year ago

There are some problems with notify_fork() API that make it not really safe to use on (at least) Linux.

After a fork() system call the child can safely call only async-signal-safe functions (at least until it calls execve()).

There are some examples in Asio where this requirement isn't obeyed. For example the epoll reactor calls at least timerfd_create(), epoll_create() and epoll_ctl() directly, timerfd_settime() via update_timeout() and eventfd() via eventfd_select_interrupter_.recreate(). It also calls POSIX mutex functions via mutex::scoped_lock.

None of these functions is guaranteed to be async-signal-safe.

Same goes, for example, for the io_uring_service or even the service_registry.

Not to mention many other methods called from these handlers which likely also contain non-async-signal-safe code.

This limitation technically applies only to multi-threaded programs, however in practice third-party libraries (even glibc) can silently create helper threads, so it's hard to be 100% certain that a program stays single-threaded.

Since these third-party library fork() calls obviously won't be wrapped in notify_fork(), every io_context would need registering with pthread_atfork(). With some trickery to de-register them after usage, since POSIX does not provide an API to do that directly.

However, even in this case it's not possible to satisfy the notify_fork() API requirement of:

This function must not be called while any other execution_context function, or any function associated with the execution_context's derived class, is being called in another thread.

That's because a third-party library can call fork() even if another thread currently calls some execution_context function.