diff options
author | Simon McVittie <smcv@collabora.com> | 2017-09-27 13:56:34 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2017-09-27 15:14:12 +0100 |
commit | 3d538ced103c7955e6e62a72866e0f56cf3f52d6 (patch) | |
tree | 456e560503b59bff493ad1047b2cd43b84f94929 /bus/main.c | |
parent | 3d557ff7b155d1e0f1cdbfd82cff0ac7ed1b7c4b (diff) | |
download | dbus-3d538ced103c7955e6e62a72866e0f56cf3f52d6.tar.gz |
Make sure non-aborting signal handlers save and restore errno
If an async signal interrupts some function, we can have this
anti-pattern:
/* in normal code */
result = some_syscall (); /* fails, e.g. errno = EINVAL */
/* interrupted by async signal handler */
write (...); /* fails, e.g. errno = ENOBUFS */
/* back to normal code */
if (errno == EINVAL) /* problem! it should be but it isn't */
The solution is for signal handlers to save and restore errno.
This is unnecessary for signal handlers that can't touch errno (like
the one in dbus-launch that just sets a flag), and for signal handlers
that never return (like the one in test-utils-glib for timeouts).
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=103010
Signed-off-by: Simon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall <withnall@endlessm.com>
Diffstat (limited to 'bus/main.c')
-rw-r--r-- | bus/main.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -67,6 +67,10 @@ typedef enum static void signal_handler (int sig) { + /* Signal handlers that might set errno must save and restore the errno + * that the interrupted function might have been relying on. */ + int saved_errno = errno; + switch (sig) { case SIGHUP: @@ -134,6 +138,8 @@ signal_handler (int sig) * signal, but keep -Wswitch-default happy */ break; } + + errno = saved_errno; } #endif /* DBUS_UNIX */ |