mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Option -S for controlling signals' logging
This commit is contained in:
parent
02483ff39e
commit
eeabf31e04
4 changed files with 123 additions and 20 deletions
4
CHANGES
4
CHANGES
|
@ -13,6 +13,10 @@ Features:
|
||||||
The number of warnings has been reduced, e.g.removing a non existing
|
The number of warnings has been reduced, e.g.removing a non existing
|
||||||
file does in most cases no longer log a warning.
|
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:
|
Corrections:
|
||||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
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/
|
0, its last sent data might have been lost depending on timing of read/
|
||||||
|
|
|
@ -176,6 +176,15 @@ label(option_s)dit(bf(tt(-s)))
|
||||||
option, socat() is sloppy with errors and tries to continue. Even with this
|
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
|
option, socat will exit on fatals, and will abort connection attempts when
|
||||||
security checks failed.
|
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>))
|
label(option_t)dit(bf(tt(-t))tt(<timeout>))
|
||||||
When one channel has reached EOF, the write part of the other channel is shut
|
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
|
down. Then, socat() waits <timeout> [link(timeval)(TYPE_TIMEVAL)] seconds
|
||||||
|
|
41
socat.c
41
socat.c
|
@ -39,6 +39,7 @@ struct {
|
||||||
int sniffleft; /* -1 or an FD for teeing data arriving on xfd1 */
|
int sniffleft; /* -1 or an FD for teeing data arriving on xfd1 */
|
||||||
int sniffright; /* -1 or an FD for teeing data arriving on xfd2 */
|
int sniffright; /* -1 or an FD for teeing data arriving on xfd2 */
|
||||||
xiolock_t lock; /* a lock file */
|
xiolock_t lock; /* a lock file */
|
||||||
|
unsigned long log_sigs; /* signals to be caught just for logging */
|
||||||
} socat_opts = {
|
} socat_opts = {
|
||||||
8192, /* bufsiz */
|
8192, /* bufsiz */
|
||||||
false, /* verbose */
|
false, /* verbose */
|
||||||
|
@ -54,6 +55,7 @@ struct {
|
||||||
-1, /* sniffleft */
|
-1, /* sniffleft */
|
||||||
-1, /* sniffright */
|
-1, /* sniffright */
|
||||||
{ NULL, 0 }, /* lock */
|
{ 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);
|
void socat_usage(FILE *fd);
|
||||||
|
@ -241,6 +243,18 @@ int main(int argc, const char *argv[]) {
|
||||||
break;
|
break;
|
||||||
case 's': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); }
|
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;
|
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]) {
|
case 't': if (arg1[0][2]) {
|
||||||
a = *arg1+2;
|
a = *arg1+2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -370,19 +384,17 @@ int main(int argc, const char *argv[]) {
|
||||||
|
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
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_flags = 0;
|
||||||
act.sa_handler = socat_signal;
|
act.sa_handler = socat_signal;
|
||||||
/* not sure which signals should be caught and print a message */
|
/* not sure which signals should be caught and print a message */
|
||||||
Sigaction(SIGHUP, &act, NULL);
|
for (i = 0, m = 1; i < 8*sizeof(unsigned long); ++i, m <<= 1) {
|
||||||
Sigaction(SIGINT, &act, NULL);
|
if (socat_opts.log_sigs & m) {
|
||||||
Sigaction(SIGQUIT, &act, NULL);
|
Sigaction(i, &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);
|
|
||||||
}
|
}
|
||||||
Signal(SIGPIPE, SIG_IGN);
|
Signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
@ -429,7 +441,7 @@ void socat_usage(FILE *fd) {
|
||||||
fputs(" -lf<logfile> log to file\n", fd);
|
fputs(" -lf<logfile> log to file\n", fd);
|
||||||
fputs(" -ls log to stderr (default if no other log)\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(" -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(" -lu use microseconds for logging timestamps\n", fd);
|
||||||
fputs(" -lh add hostname to log messages\n", fd);
|
fputs(" -lh add hostname to log messages\n", fd);
|
||||||
fputs(" -v verbose text dump of data traffic\n", fd);
|
fputs(" -v verbose text dump of data traffic\n", fd);
|
||||||
|
@ -438,6 +450,7 @@ void socat_usage(FILE *fd) {
|
||||||
fputs(" -R <file> raw dump of data flowing from right to left\n", fd);
|
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(" -b<size_t> set data buffer size (8192)\n", fd);
|
||||||
fputs(" -s sloppy (continue on error)\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> wait seconds before closing second channel\n", fd);
|
||||||
fputs(" -T<timeout> total inactivity timeout in seconds\n", fd);
|
fputs(" -T<timeout> total inactivity timeout in seconds\n", fd);
|
||||||
fputs(" -u unidirectional mode (left to right)\n", fd);
|
fputs(" -u unidirectional mode (left to right)\n", fd);
|
||||||
|
@ -1593,11 +1606,7 @@ void socat_signal(int signum) {
|
||||||
diag_in_handler = 1;
|
diag_in_handler = 1;
|
||||||
Notice1("socat_signal(): handling signal %d", signum);
|
Notice1("socat_signal(): handling signal %d", signum);
|
||||||
switch (signum) {
|
switch (signum) {
|
||||||
case SIGILL:
|
default:
|
||||||
case SIGABRT:
|
|
||||||
case SIGBUS:
|
|
||||||
case SIGFPE:
|
|
||||||
case SIGSEGV:
|
|
||||||
diag_immediate_exit = 1;
|
diag_immediate_exit = 1;
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
|
|
89
test.sh
89
test.sh
|
@ -4267,7 +4267,7 @@ case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%$NAME%*)
|
||||||
if ! eval $NUMCOND; then :
|
if ! eval $NUMCOND; then :
|
||||||
elif ! F=$(testfeats STDIO EXEC); 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))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! A=$(testaddrs STDIO EXEC); then
|
elif ! A=$(testaddrs STDIO EXEC); then
|
||||||
|
@ -9271,7 +9271,7 @@ case "$TESTS" in
|
||||||
TEST="$NAME: UDP/IPv6 multicast"
|
TEST="$NAME: UDP/IPv6 multicast"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! f=$(testfeats ip6 udp); 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))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! a=$(testaddrs - STDIO UDP6-RECV UDP6-SENDTO); then
|
elif ! a=$(testaddrs - STDIO UDP6-RECV UDP6-SENDTO); then
|
||||||
|
@ -16127,7 +16127,7 @@ TEST="$NAME: ${KEYW}-RECVFROM with fork option"
|
||||||
# When the second record is stored before the first one the test succeeded.
|
# When the second record is stored before the first one the test succeeded.
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! F=$(testfeats $FEAT STDIO SYSTEM); 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))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! A=$(testaddrs - STDIO SYSTEM $PROTO-RECVFROM $PROTO-SENDTO); then
|
elif ! A=$(testaddrs - STDIO SYSTEM $PROTO-RECVFROM $PROTO-SENDTO); then
|
||||||
|
@ -16205,6 +16205,87 @@ UDP6 UDP udp4 [::1] PORT
|
||||||
UNIX unix unix $td/test\$N.server -
|
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
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -16355,7 +16436,7 @@ elif ! $(type systemd-socket-activate >/dev/null 2>&1); then
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! F=$(testfeats STDIO IP4 TCP PIPE); then
|
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))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! A=$(testaddrs - TCP4 TCP4-LISTEN PIPE); then
|
elif ! A=$(testaddrs - TCP4 TCP4-LISTEN PIPE); then
|
||||||
|
|
Loading…
Reference in a new issue