mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
fixed bugs where sub processes would become zombies because the master process did not catch SIGCHLD
This commit is contained in:
parent
c44985fb8d
commit
1f5165b765
13 changed files with 116 additions and 55 deletions
6
CHANGES
6
CHANGES
|
@ -16,6 +16,12 @@ corrections:
|
|||
fix: replaced FOPEN_MAX with FD_SETSIZE
|
||||
thanks to Daniel Lucq for reporting this problem.
|
||||
|
||||
fixed bugs where sub processes would become zombies because the master
|
||||
process did not catch SIGCHLD. this affected addresses UDP-LISTEN,
|
||||
UDP-CONNECT, TCP-CONNECT, OPENSSL, PROXY, UNIX-CONNECT, UNIX-CLIENT,
|
||||
ABSTRACT-CONNECT, ABSTRACT-CLIENT, SOCKSA, SOCKS4A
|
||||
(thanks to Fernanda G Weiden for reporting this problem)
|
||||
|
||||
corrected some print statements and variable names
|
||||
|
||||
make uninstall did not uninstall procan
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.6.0.0+execpty+servres+fd_setsize"
|
||||
"1.6.0.0+execpty+servres+fd_setsize+udp_sigchld1"
|
||||
|
|
50
test.sh
50
test.sh
|
@ -7979,6 +7979,56 @@ esac
|
|||
N=$((N+1))
|
||||
|
||||
|
||||
# there was a bug with udp-listen and fork: terminating sub processes became
|
||||
# zombies because the master process did not catch SIGCHLD
|
||||
NAME=UDP4LISTEN_SIGCHLD
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%$NAME%*)
|
||||
TEST="$NAME: test if UDP4-LISTEN child becomes zombie"
|
||||
# idea: run a udp-listen process with fork and -T. Connect once, so a sub
|
||||
# process is forked off. Make some transfer and wait until the -T timeout is
|
||||
# over. Now check for the child process: if it is zombie the test failed.
|
||||
# Correct is that child process terminated
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
tsl=$PORT
|
||||
ts="$LOCALHOST:$tsl"
|
||||
da=$(date)
|
||||
CMD1="$SOCAT $opts -T 0.5 UDP4-LISTEN:$tsl,reuseaddr,fork PIPE"
|
||||
CMD2="$SOCAT $opts - UDP4:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 >"$tf" 2>"${te}1" &
|
||||
pid1=$!
|
||||
waitudp4port $tsl 1
|
||||
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
||||
rc2=$?
|
||||
sleep 1
|
||||
#read -p ">"
|
||||
l="$(childprocess $pid1)"
|
||||
kill $pid1 2>/dev/null; wait
|
||||
if [ $rc2 -ne 0 ]; then
|
||||
$PRINTF "$NO_RESULT\n" # already handled in test UDP4STREAM
|
||||
numCANT=$((numCANT+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$NO_RESULT\n" # already handled in test UDP4STREAM
|
||||
numCANT=$((numCANT+1))
|
||||
elif $(isdefunct "$l"); then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "${te}1" "${te}2"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
|
||||
|
||||
if [ "$numFAIL" -gt 0 ]; then
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-ipapp.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for TCP and UDP related options */
|
||||
|
@ -57,6 +57,10 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if (xioopts.logopt == 'm') {
|
||||
Info("starting connect loop, switching to syslog");
|
||||
diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
|
||||
|
|
23
xio-listen.c
23
xio-listen.c
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-listen.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for listen socket options */
|
||||
|
@ -115,28 +115,9 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
||||
#if 1
|
||||
if (dofork) {
|
||||
#if HAVE_SIGACTION
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(struct sigaction));
|
||||
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
|
||||
#ifdef SA_NOMASK
|
||||
|SA_NOMASK
|
||||
#endif
|
||||
;
|
||||
act.sa_handler = childdied;
|
||||
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
||||
/*! man does not say that errno is defined */
|
||||
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
#else /* HAVE_SIGACTION */
|
||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||
}
|
||||
#endif /* !HAVE_SIGACTION */
|
||||
}
|
||||
#endif /* 1 */
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-openssl.c */
|
||||
/* Copyright Gerhard Rieger 2002-2007 */
|
||||
/* Copyright Gerhard Rieger 2002-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the implementation of the openssl addresses */
|
||||
|
@ -268,6 +268,10 @@ static int
|
|||
default: return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
#if WITH_RETRY
|
||||
if (dofork) {
|
||||
pid_t pid;
|
||||
|
|
|
@ -399,9 +399,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
||||
return STAT_RETRYLATER;*/
|
||||
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||
}
|
||||
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
|
||||
if (withfork) {
|
||||
const char *forkwaitstring;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-proxy.c */
|
||||
/* Copyright Gerhard Rieger 2002-2006 */
|
||||
/* Copyright Gerhard Rieger 2002-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of HTTP proxy CONNECT
|
||||
|
@ -185,6 +185,10 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
return result;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
#if WITH_RETRY
|
||||
if (dofork) {
|
||||
pid_t pid;
|
||||
|
|
29
xio-socket.c
29
xio-socket.c
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-socket.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for socket related functions */
|
||||
|
@ -401,6 +401,10 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
return result;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
#if WITH_RETRY
|
||||
if (dofork) {
|
||||
pid_t pid;
|
||||
|
@ -554,29 +558,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
#if 1
|
||||
if (dofork) {
|
||||
#if HAVE_SIGACTION
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(struct sigaction));
|
||||
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
|
||||
#ifdef SA_NOMASK
|
||||
|SA_NOMASK
|
||||
#endif
|
||||
;
|
||||
act.sa_handler = childdied;
|
||||
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
||||
/*! man does not say that errno is defined */
|
||||
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
|
||||
}
|
||||
#else /* HAVE_SIGACTION */
|
||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||
}
|
||||
#endif /* !HAVE_SIGACTION */
|
||||
}
|
||||
#endif /* 1 */
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-socks.c */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of socks4 type */
|
||||
|
@ -163,6 +163,10 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
return result;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
#if WITH_RETRY
|
||||
if (dofork) {
|
||||
pid_t pid;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-udp.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for handling UDP addresses */
|
||||
|
@ -164,6 +164,10 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
retropt_bool(opts, OPT_LOWPORT, &fd->stream.para.socket.ip.lowport);
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
while (true) { /* we loop with fork or prohibited packets */
|
||||
/* now wait for some packet on this datagram socket, get its sender
|
||||
address, connect there, and return */
|
||||
|
|
1
xio.h
1
xio.h
|
@ -388,6 +388,7 @@ extern pid_t diedunknown3;
|
|||
extern pid_t diedunknown4;
|
||||
|
||||
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
|
||||
extern int xiosetchilddied(void);
|
||||
extern int xio_opt_signal(pid_t pid, int signum);
|
||||
extern void childdied(int signum);
|
||||
|
||||
|
|
25
xiosigchld.c
25
xiosigchld.c
|
@ -1,5 +1,5 @@
|
|||
/* source: xiosigchld.c */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this is the source of the extended child signal handler */
|
||||
|
@ -157,3 +157,26 @@ void childdied(int signum) {
|
|||
Info("childdied() finished");
|
||||
errno = _errno;
|
||||
}
|
||||
|
||||
|
||||
int xiosetchilddied(void) {
|
||||
#if HAVE_SIGACTION
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(struct sigaction));
|
||||
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
|
||||
#ifdef SA_NOMASK
|
||||
|SA_NOMASK
|
||||
#endif
|
||||
;
|
||||
act.sa_handler = childdied;
|
||||
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
||||
/*! man does not say that errno is defined */
|
||||
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
|
||||
}
|
||||
#else /* HAVE_SIGACTION */
|
||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||
}
|
||||
#endif /* !HAVE_SIGACTION */
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue