Option -S for controlling signals' logging
diff --git a/CHANGES b/CHANGES
index 1da4617..5b019c4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,10 @@
The number of warnings has been reduced, e.g.removing a non existing
file does in most cases no longer log a warning.
+ New option -S <mask> controls catching and logging of signals that are
+ not internally used by Socat.
+ Tests: SIGTERM_NOLOG SIG31_LOG
+
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/
diff --git a/doc/socat.yo b/doc/socat.yo
index 6a6619a..175d734 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -176,6 +176,15 @@
option, socat() is sloppy with errors and tries to continue. Even with this
option, socat will exit on fatals, and will abort connection attempts when
security checks failed.
+label(option_S)dit(bf(tt(-S))tt(<signals-bitmap>))
+ Changes the set of signals that are caught by socat() just for printing an
+ log message. This catching is useful to get the information about the signal
+ into socat()s log, but prevents core dump or other standard actions. The
+ default set of these signals is SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
+ SIGBUS, SIGFPE, SIGSEGV, and SIGTERM; replace this set (0x89de on Linux)
+ with a bitmap (e.g., SIGFPE has value 8 and its bit is 0x0080).nl()
+ Note: Signals SIGHUP, SIGINT, SIGQUIT, SIGUSR1, SIGPIPE, SIGALRM, SIGTERM, and
+ SIGCHLD may be handled specially anyway.
label(option_t)dit(bf(tt(-t))tt(<timeout>))
When one channel has reached EOF, the write part of the other channel is shut
down. Then, socat() waits <timeout> [link(timeval)(TYPE_TIMEVAL)] seconds
diff --git a/socat.c b/socat.c
index 6488103..98c7e7e 100644
--- a/socat.c
+++ b/socat.c
@@ -39,6 +39,7 @@
int sniffleft; /* -1 or an FD for teeing data arriving on xfd1 */
int sniffright; /* -1 or an FD for teeing data arriving on xfd2 */
xiolock_t lock; /* a lock file */
+ unsigned long log_sigs; /* signals to be caught just for logging */
} socat_opts = {
8192, /* bufsiz */
false, /* verbose */
@@ -54,6 +55,7 @@
-1, /* sniffleft */
-1, /* sniffright */
{ NULL, 0 }, /* lock */
+ 1<<SIGHUP | 1<<SIGINT | 1<<SIGQUIT | 1<<SIGILL | 1<<SIGABRT | 1<<SIGBUS | 1<<SIGFPE | 1<<SIGSEGV | 1<<SIGTERM, /* log_sigs */
};
void socat_usage(FILE *fd);
@@ -241,6 +243,18 @@
break;
case 's': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); }
diag_set_int('e', E_FATAL); break;
+ case 'S': /* do not catch signals */
+ if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -S requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ socat_opts.log_sigs = Strtoul(a, (char **)&a, 0, "-S");
+ break;
case 't': if (arg1[0][2]) {
a = *arg1+2;
} else {
@@ -370,19 +384,17 @@
{
struct sigaction act;
- sigfillset(&act.sa_mask);
+ int i, m;
+
+ sigfillset(&act.sa_mask); /* while in sighandler block all signals */
act.sa_flags = 0;
act.sa_handler = socat_signal;
/* not sure which signals should be caught and print a message */
- Sigaction(SIGHUP, &act, NULL);
- Sigaction(SIGINT, &act, NULL);
- Sigaction(SIGQUIT, &act, NULL);
- Sigaction(SIGILL, &act, NULL);
- Sigaction(SIGABRT, &act, NULL);
- Sigaction(SIGBUS, &act, NULL);
- Sigaction(SIGFPE, &act, NULL);
- Sigaction(SIGSEGV, &act, NULL);
- Sigaction(SIGTERM, &act, NULL);
+ for (i = 0, m = 1; i < 8*sizeof(unsigned long); ++i, m <<= 1) {
+ if (socat_opts.log_sigs & m) {
+ Sigaction(i, &act, NULL);
+ }
+ }
}
Signal(SIGPIPE, SIG_IGN);
@@ -429,7 +441,7 @@
fputs(" -lf<logfile> log to file\n", fd);
fputs(" -ls log to stderr (default if no other log)\n", fd);
fputs(" -lm[facility] mixed log mode (stderr during initialization, then syslog)\n", fd);
- fputs(" -lp<progname> set the program name used for logging\n", fd);
+ fputs(" -lp<progname> set the program name used for logging and vars\n", fd);
fputs(" -lu use microseconds for logging timestamps\n", fd);
fputs(" -lh add hostname to log messages\n", fd);
fputs(" -v verbose text dump of data traffic\n", fd);
@@ -438,6 +450,7 @@
fputs(" -R <file> raw dump of data flowing from right to left\n", fd);
fputs(" -b<size_t> set data buffer size (8192)\n", fd);
fputs(" -s sloppy (continue on error)\n", fd);
+ fputs(" -S<sigmask> log these signals, override default\n", fd);
fputs(" -t<timeout> wait seconds before closing second channel\n", fd);
fputs(" -T<timeout> total inactivity timeout in seconds\n", fd);
fputs(" -u unidirectional mode (left to right)\n", fd);
@@ -1593,11 +1606,7 @@
diag_in_handler = 1;
Notice1("socat_signal(): handling signal %d", signum);
switch (signum) {
- case SIGILL:
- case SIGABRT:
- case SIGBUS:
- case SIGFPE:
- case SIGSEGV:
+ default:
diag_immediate_exit = 1;
case SIGQUIT:
case SIGPIPE:
diff --git a/test.sh b/test.sh
index 0cb66b5..963d010 100755
--- a/test.sh
+++ b/test.sh
@@ -4267,7 +4267,7 @@
*%$N%*|*%functions%*|*%$NAME%*)
if ! eval $NUMCOND; then :
elif ! F=$(testfeats STDIO EXEC); then
- $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available in $SOCAT${NORMAL}\n" $N
+ $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs STDIO EXEC); then
@@ -9271,7 +9271,7 @@
TEST="$NAME: UDP/IPv6 multicast"
if ! eval $NUMCOND; then :;
elif ! f=$(testfeats ip6 udp); then
- $PRINTF "test $F_n $TEST... ${YELLOW}Feature $f not available in $SOCAT${NORMAL}\n" $N
+ $PRINTF "test $F_n $TEST... ${YELLOW}Feature $f not configured in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! a=$(testaddrs - STDIO UDP6-RECV UDP6-SENDTO); then
@@ -16127,7 +16127,7 @@
# When the second record is stored before the first one the test succeeded.
if ! eval $NUMCOND; then :;
elif ! F=$(testfeats $FEAT STDIO SYSTEM); then
- $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
+ $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs - STDIO SYSTEM $PROTO-RECVFROM $PROTO-SENDTO); then
@@ -16205,6 +16205,87 @@
UNIX unix unix $td/test\$N.server -
"
+
+# Test if option -S turns off logging of SIGTERM
+NAME=SIGTERM_NOLOG
+case "$TESTS" in
+*%$N%*|*%functions%*|*%signal%*|*%$NAME%*)
+TEST="$NAME: Option -S can turn off logging of SIGTERM"
+# Start Socat with option -S 0x0000, kill it with SIGTERM
+# When no logging entry regarding this signal is there, the test succeeded
+if ! eval $NUMCOND; then :;
+else
+tf="$td/test$N.stdout"
+te="$td/test$N.stderr"
+tdiff="$td/test$N.diff"
+da="test$N $(date) $RANDOM"
+newport tcp4 # or whatever proto, or drop this line
+CMD0="$TRACE $SOCAT $opts -S 0x0000 PIPE PIPE"
+printf "test $F_n $TEST... " $N
+$CMD0 >/dev/null 2>"${te}0" &
+pid0=$!
+relsleep 1 # give process time to start
+kill -TERM $pid0 2>/dev/null; wait
+if ! grep -q "exiting on signal" ${te}0; then
+ $PRINTF "$OK\n"
+ if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+ if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
+ if [ "$DEBUG" ]; then echo "kill -TERM <pid>" >&2; fi
+ numOK=$((numOK+1))
+else
+ $PRINTF "$FAILED\n"
+ echo "$CMD0 &"
+ cat "${te}0" >&2
+ echo "kill -TERM <pid>" >&2
+ numFAIL=$((numFAIL+1))
+ listFAIL="$listFAIL $N"
+ namesFAIL="$namesFAIL $NAME"
+fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+# Test if option -S turns on logging of signal 31
+NAME=SIG31_LOG
+case "$TESTS" in
+*%$N%*|*%functions%*|*%signal%*|*%$NAME%*)
+TEST="$NAME: Option -S can turn on logging of signal 31"
+# Start Socat with option -S 0x80000000, kill it with -31
+# When a logging entry regarding this signal is there, the test succeeded
+if ! eval $NUMCOND; then :;
+else
+tf="$td/test$N.stdout"
+te="$td/test$N.stderr"
+tdiff="$td/test$N.diff"
+da="test$N $(date) $RANDOM"
+newport tcp4 # or whatever proto, or drop this line
+CMD0="$TRACE $SOCAT $opts -S 0x80000000 PIPE PIPE"
+printf "test $F_n $TEST... " $N
+$CMD0 >/dev/null 2>"${te}0" &
+pid0=$!
+relsleep 1 # give process time to start
+kill -31 $pid0 2>/dev/null; wait
+if grep -q "exiting on signal" ${te}0; then
+ $PRINTF "$OK\n"
+ if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+ if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
+ if [ "$DEBUG" ]; then echo "kill -31 <pid>" >&2; fi
+ numOK=$((numOK+1))
+else
+ $PRINTF "$FAILED\n"
+ echo "$CMD0 &"
+ cat "${te}0" >&2
+ echo "kill -31 <pid>" >&2
+ numFAIL=$((numFAIL+1))
+ listFAIL="$listFAIL $N"
+ namesFAIL="$namesFAIL $NAME"
+fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
# end of common tests
##################################################################################
@@ -16355,7 +16436,7 @@
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! F=$(testfeats STDIO IP4 TCP PIPE); then
- $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available in $SOCAT${NORMAL}\n" $N
+ $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs - TCP4 TCP4-LISTEN PIPE); then