Aha. My testing was off, this makes more sense now.
The problem is indeed epoll-backend related. The problem is that
after the fork, the subprocess shares the epoll fd with the parent
process, and these both refer to the same kernel epoll structure.
Ordinarily, you would call event_reinit() before using it, so that the
subprocess would now have its own separate structure. But if you
instead call event_base_free() immediately, the subprocess calls
evsig_dealloc(), which calls event_del() on the ev_signal event, which
unregisters it from the shared epoll structure, so the master process
doesn't get signal events any more.
The workaround for now is to do event_reinit() *then*
event_base_free() in the subprocess. I've tested it, and it seems to
work on Linux for me.