Process last data of failed child process
diff --git a/CHANGES b/CHANGES
index b9b0a4f..60deebf 100644
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,14 @@
 	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 @@
    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 @@
 #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 @@
 	    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 @@
 	 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",