From a0e17a813aa8babbbc9cdd1d4fafc5e998f8e4a0 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Thu, 15 Jun 2023 12:53:32 +0200 Subject: [PATCH] Process last data of failed child process --- CHANGES | 8 ++++++++ socat.c | 3 +++ xio.h | 1 + xiosigchld.c | 7 +++++-- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index b9b0a4f..60deebf 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,14 @@ Features: The number of warnings has been reduced, e.g.removing a non existing file does in most cases no longer log a warning. +Corrections: + When a sub process (EXEC, SYSTEM) terminated with exit code other than + 0, its last sent data might have been lost depending on timing of read/ + write and SIGCHLD in Socat. + Now the SIGCHLD handler does not simply terminate Socat in this case, + but remembers the failure and allows further processing. + Thanks to Luke Jones for reporting this issue. + Coding: Introduced groups_t instead of uint32_t, for more flexibility diff --git a/socat.c b/socat.c index 78c895c..873920c 100644 --- a/socat.c +++ b/socat.c @@ -399,6 +399,9 @@ int main(int argc, const char *argv[]) { Atexit(socat_unlock); result = socat(arg1[0], arg1[1]); + if (result == EXIT_SUCCESS && engine_result != EXIT_SUCCESS) { + result = engine_result; /* a signal handler reports failure */ + } Notice1("exiting with status %d", result); Exit(result); return 0; /* not reached, just for gcc -Wall */ diff --git a/xio.h b/xio.h index e10daf3..92035e6 100644 --- a/xio.h +++ b/xio.h @@ -461,6 +461,7 @@ extern pid_t diedunknown[NUMUNKNOWN]; /* child died before it is registered */ #define diedunknown3 (diedunknown[2]) #define diedunknown4 (diedunknown[3]) extern int statunknown[NUMUNKNOWN]; /* exit state of unknown dead child */ +extern int engine_result; /* here signal handler overrides OK */ extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)); extern int xiosetchilddied(void); diff --git a/xiosigchld.c b/xiosigchld.c index ca88f63..98abb70 100644 --- a/xiosigchld.c +++ b/xiosigchld.c @@ -13,6 +13,7 @@ pid_t diedunknown[NUMUNKNOWN]; /* children that died before they were registered */ int statunknown[NUMUNKNOWN]; /* exit state of unknown dead child */ size_t nextunknown; +int engine_result = EXIT_SUCCESS; /* register for a xio filedescriptor a callback (handler). @@ -138,8 +139,9 @@ void childdied(int signum) { Info2("waitpid(): child %d exited with status %d", pid, WEXITSTATUS(status)); } else { - Error2("waitpid(): child %d exited with status %d", + Warn2("waitpid(): child %d exited with status %d", pid, WEXITSTATUS(status)); + engine_result = 1; } } } else if (WIFSIGNALED(status)) { @@ -147,8 +149,9 @@ void childdied(int signum) { Info2("waitpid(): child %d exited on signal %d", pid, WTERMSIG(status)); } else { - Error2("waitpid(): child %d exited on signal %d", + Warn2("waitpid(): child %d exited on signal %d", pid, WTERMSIG(status)); + engine_result = 1; } } else if (WIFSTOPPED(status)) { Info2("waitpid(): child %d stopped on signal %d",