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
|
fix: replaced FOPEN_MAX with FD_SETSIZE
|
||||||
thanks to Daniel Lucq for reporting this problem.
|
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
|
corrected some print statements and variable names
|
||||||
|
|
||||||
make uninstall did not uninstall procan
|
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))
|
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"
|
echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
|
||||||
|
|
||||||
if [ "$numFAIL" -gt 0 ]; then
|
if [ "$numFAIL" -gt 0 ]; then
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-ipapp.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for TCP and UDP related options */
|
/* 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;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
if (xioopts.logopt == 'm') {
|
if (xioopts.logopt == 'm') {
|
||||||
Info("starting connect loop, switching to syslog");
|
Info("starting connect loop, switching to syslog");
|
||||||
diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
|
diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
|
||||||
|
|
23
xio-listen.c
23
xio-listen.c
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-listen.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for listen socket options */
|
/* 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 (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
#if HAVE_SIGACTION
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
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) {
|
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-openssl.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the implementation of the openssl addresses */
|
/* this file contains the implementation of the openssl addresses */
|
||||||
|
@ -268,6 +268,10 @@ static int
|
||||||
default: return STAT_NORETRY;
|
default: return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
|
@ -399,9 +399,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
||||||
return STAT_RETRYLATER;*/
|
return STAT_RETRYLATER;*/
|
||||||
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
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) {
|
if (withfork) {
|
||||||
const char *forkwaitstring;
|
const char *forkwaitstring;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-proxy.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of HTTP proxy CONNECT
|
/* 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
29
xio-socket.c
29
xio-socket.c
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-socket.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for socket related functions */
|
/* 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid_t pid;
|
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 (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) {
|
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-socks.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of socks4 type */
|
/* 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-udp.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for handling UDP addresses */
|
/* 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);
|
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 */
|
while (true) { /* we loop with fork or prohibited packets */
|
||||||
/* now wait for some packet on this datagram socket, get its sender
|
/* now wait for some packet on this datagram socket, get its sender
|
||||||
address, connect there, and return */
|
address, connect there, and return */
|
||||||
|
|
1
xio.h
1
xio.h
|
@ -388,6 +388,7 @@ extern pid_t diedunknown3;
|
||||||
extern pid_t diedunknown4;
|
extern pid_t diedunknown4;
|
||||||
|
|
||||||
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
|
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 int xio_opt_signal(pid_t pid, int signum);
|
||||||
extern void childdied(int signum);
|
extern void childdied(int signum);
|
||||||
|
|
||||||
|
|
25
xiosigchld.c
25
xiosigchld.c
|
@ -1,5 +1,5 @@
|
||||||
/* source: xiosigchld.c */
|
/* 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 */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this is the source of the extended child signal handler */
|
/* this is the source of the extended child signal handler */
|
||||||
|
@ -157,3 +157,26 @@ void childdied(int signum) {
|
||||||
Info("childdied() finished");
|
Info("childdied() finished");
|
||||||
errno = _errno;
|
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