mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Retry write on EINTR in signal handler
The signal handler writes the received signal number as a byte value into the notification pipe. If two signals are received in quick succession, one of the writes may fail with EINTR without writing the byte. This commit will check for EINTR and retry the write. If the error is other than EINTR, a warning will be logged. Note, that: - on systems with sigaction libevent uses sigaction with SA_RESTART - on linux writing to pipe is restartable and firstly it will try to write that byte so linux should not be affected in any form [1]. [1]: https://elixir.bootlin.com/linux/latest/source/fs/pipe.c#L545
This commit is contained in:
parent
dff8fd27ed
commit
4f8a61446c
22
signal.c
22
signal.c
@ -400,9 +400,25 @@ evsig_handler(int sig)
|
||||
#ifdef _WIN32
|
||||
send(evsig_base_fd, (char*)&msg, 1, 0);
|
||||
#else
|
||||
{
|
||||
int r = write(evsig_base_fd, (char*)&msg, 1);
|
||||
(void)r; /* Suppress 'unused return value' and 'unused var' */
|
||||
for (;;) {
|
||||
/*
|
||||
* errno is only set to provide a descriptive message for event_warnx
|
||||
* if write returns 0. Not setting it will result in "No error" message
|
||||
* because write does not set errno when returning 0.
|
||||
*
|
||||
* EAGAIN will print "Try again" message. Another idea is to use
|
||||
* ENOSPC, but since we use non blocking sockets EAGAIN is preferable.
|
||||
*
|
||||
* Other than setting this text of the logged warning, the value in
|
||||
* errno has no further effect.
|
||||
*/
|
||||
errno = EAGAIN;
|
||||
if (0 >= write(evsig_base_fd, &msg, 1)) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
event_warnx("%s: write: %s", __func__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
errno = save_errno;
|
||||
|
Loading…
x
Reference in New Issue
Block a user