Message ID | 20211112201054.3493178-1-JPEWhacker@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | Fix deadlock from calling exit() in signal handler | expand |
Hi Joshua, On 12.11.21 21:10, Joshua Watt wrote: > exit() cannot be called from a signal handler in swupdate because the > atexit() handlers are not thread-safe and can deadlock. Right. > Instead, signal > the main process to exit with SIGTERM when a child process dies. > > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> > --- > core/pctl.c | 11 ++++++----- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/core/pctl.c b/core/pctl.c > index 9c2d534..c31575a 100644 > --- a/core/pctl.c > +++ b/core/pctl.c > @@ -404,7 +404,6 @@ int run_system_cmd(const char *cmd) > void sigchld_handler (int __attribute__ ((__unused__)) signum) > { > int childpid, status, serrno; > - int exitstatus; > int hasdied = 0; > int i; > > @@ -427,11 +426,9 @@ void sigchld_handler (int __attribute__ ((__unused__)) signum) > hasdied = 0; > if (WIFEXITED(status)) { > hasdied = 1; > - exitstatus = WEXITSTATUS(status); > - printf("exited, status=%d\n", exitstatus); > + printf("exited, status=%d\n", WIFEXITED(status)); > } else if (WIFSIGNALED(status)) { > hasdied = 1; > - exitstatus = WTERMSIG(status); > printf("killed by signal %d\n", WTERMSIG(status)); > } else if (WIFSTOPPED(status)) { > printf("stopped by signal %d\n", WSTOPSIG(status)); > @@ -454,7 +451,11 @@ void sigchld_handler (int __attribute__ ((__unused__)) signum) > } > } > > - exit(exitstatus); > + /* > + * exit() it not safe to call from a signal handler because of atexit() > + * handlers, so send SIGTERM to ourself instead > + */ > + kill(getpid(), SIGTERM); > } > > errno = serrno; > Thanks for fixing, applied to -master. Best regards, Stefano Babic
diff --git a/core/pctl.c b/core/pctl.c index 9c2d534..c31575a 100644 --- a/core/pctl.c +++ b/core/pctl.c @@ -404,7 +404,6 @@ int run_system_cmd(const char *cmd) void sigchld_handler (int __attribute__ ((__unused__)) signum) { int childpid, status, serrno; - int exitstatus; int hasdied = 0; int i; @@ -427,11 +426,9 @@ void sigchld_handler (int __attribute__ ((__unused__)) signum) hasdied = 0; if (WIFEXITED(status)) { hasdied = 1; - exitstatus = WEXITSTATUS(status); - printf("exited, status=%d\n", exitstatus); + printf("exited, status=%d\n", WIFEXITED(status)); } else if (WIFSIGNALED(status)) { hasdied = 1; - exitstatus = WTERMSIG(status); printf("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d\n", WSTOPSIG(status)); @@ -454,7 +451,11 @@ void sigchld_handler (int __attribute__ ((__unused__)) signum) } } - exit(exitstatus); + /* + * exit() it not safe to call from a signal handler because of atexit() + * handlers, so send SIGTERM to ourself instead + */ + kill(getpid(), SIGTERM); } errno = serrno;
exit() cannot be called from a signal handler in swupdate because the atexit() handlers are not thread-safe and can deadlock. Instead, signal the main process to exit with SIGTERM when a child process dies. Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> --- core/pctl.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)