libevent & signal handling (SIGCHLD specifically)

2019-07-23 19:32发布

问题:

This is somewhat of a followup to related question I found here.

In the linked question there is a mention of using signalfd() and using that fd with libevent. In that question the OP does not list why he is using signalfd() as opposed to the libevent signal handling facilities.

In both methods you would be processing the callback outside of the signal-handler.

This documentation seems to warn about scheduling timer in the signal event callback. Which doesn't seem right (as we would be outside of a signal handler context). Aside for said warning I cant see a benefit to doing this with signalfd().

Any input about the difference between the two methods or about the warning

Thanks!

回答1:

from libevent's source code (v2.0.19-stable)

/* signal.c

This is the signal-handling implementation we use for backends that don't have a better way to do signal handling. It uses sigaction() or signal() to set a signal handler, and a socket pair to tell the event base when

Note that I said "the event base" : only one event base can be set up to use this at a time. For historical reasons and backward compatibility, if you add an event for a signal to event_base A, then add an event for a signal (any signal!) to event_base B, event_base B will get informed about the signal, but event_base A won't.

It would be neat to change this behavior in some future version of Libevent. kqueue already does something far more sensible. We can make all backends on Linux do a reasonable thing using signalfd. */

so right now libevent uses sigaction() if it's available, and, failing that, signal().

if you use signalfd() you usually block the signal using sigprocmask so that the signals won't cause the default handlers to execute. then, you can monitor the returned file handle using libevent and handle the signal from normal synchronous code safely, without having to worry about memory safety or blocking or interrupting other syscalls.

there are restrictions on what you can safely do inside classic asynchronous signal handlers (i.e. those registered using sigaction). See the "Async-signal-safe functions" in man signal. Using the signalfd approach, these restrictions are greatly lessened.

the warning about registering a timer callback was likely put there as a concern because libevent supports so many platforms, and at least one person reported problems. note that if you are selecting/polling a file handle registered by signalfd then you don't have to worry about this restriction anyways.

EDIT: i re-read your question and realized I hadn't really answered it properly. the benefit of registering a signalfd and then using that in libevent is because it's faster at the expense of portability. there were plans (http://archives.seul.org/libevent/users/Mar-2010/msg00046.html) to include signalfd into libevent but AFAIK it hasn't happened yet.

also, once you've been notified of the SIGCHLD you should always call waitpid in a loop until you get ENOCHLD because both methods will collapse multiple occurences of the signal.



标签: c libevent