mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
fixed a bug where sub processes would become zombies because the master process caught SIGCHLD but did not wait()
This commit is contained in:
parent
1f5165b765
commit
3b3b004ff8
4 changed files with 84 additions and 1 deletions
5
CHANGES
5
CHANGES
|
@ -22,6 +22,11 @@ corrections:
|
||||||
ABSTRACT-CONNECT, ABSTRACT-CLIENT, SOCKSA, SOCKS4A
|
ABSTRACT-CONNECT, ABSTRACT-CLIENT, SOCKSA, SOCKS4A
|
||||||
(thanks to Fernanda G Weiden for reporting this problem)
|
(thanks to Fernanda G Weiden for reporting this problem)
|
||||||
|
|
||||||
|
fixed a bug where sub processes would become zombies because the master
|
||||||
|
process caught SIGCHLD but did not wait(). this affected addresses
|
||||||
|
UDP-RECVFROM, IP-RECVFROM, UNIX-RECVFROM, ABSTRACT-RECVFROM
|
||||||
|
(thanks to Evan Borgstrom 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+udp_sigchld1"
|
"1.6.0.0+execpty+servres+fd_setsize+udp_sigchld"
|
||||||
|
|
50
test.sh
50
test.sh
|
@ -8029,6 +8029,56 @@ PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# there was a bug with udp-recvfrom and fork: terminating sub processes became
|
||||||
|
# zombies because the master process did caught SIGCHLD but did not wait()
|
||||||
|
NAME=UDP4RECVFROM_SIGCHLD
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test if UDP4-RECVFROM child becomes zombie"
|
||||||
|
# idea: run a udp-recvfrom process with fork and -T. Sent it one packet, 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-RECVFROM:$tsl,reuseaddr,fork PIPE"
|
||||||
|
CMD2="$SOCAT $opts - UDP4-SENDTO:$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 UDP4DGRAM
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
|
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAMM
|
||||||
|
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
|
||||||
|
|
28
xio-socket.c
28
xio-socket.c
|
@ -512,9 +512,37 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||||
static pid_t xio_waitingfor;
|
static pid_t xio_waitingfor;
|
||||||
static bool xio_hashappened;
|
static bool xio_hashappened;
|
||||||
void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) {
|
void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) {
|
||||||
|
pid_t pid;
|
||||||
|
int _errno;
|
||||||
|
int status = 0;
|
||||||
|
bool wassig = false;
|
||||||
Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
|
Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
|
||||||
signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
|
signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
|
||||||
siginfo->si_pid);
|
siginfo->si_pid);
|
||||||
|
_errno = errno;
|
||||||
|
do {
|
||||||
|
pid = Waitpid(-1, &status, WNOHANG);
|
||||||
|
if (pid == 0) {
|
||||||
|
Msg(wassig?E_INFO:E_WARN,
|
||||||
|
"waitpid(-1, {}, WNOHANG): no child has exited");
|
||||||
|
Info("childdied() finished");
|
||||||
|
errno = _errno;
|
||||||
|
return;
|
||||||
|
} else if (pid < 0 && errno == ECHILD) {
|
||||||
|
Msg1(wassig?E_INFO:E_WARN,
|
||||||
|
"waitpid(-1, {}, WNOHANG): %s", strerror(errno));
|
||||||
|
Info("childdied() finished");
|
||||||
|
errno = _errno;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wassig = true;
|
||||||
|
if (pid < 0) {
|
||||||
|
Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno));
|
||||||
|
Info("childdied() finished");
|
||||||
|
errno = _errno;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
if (xio_waitingfor == siginfo->si_pid) {
|
if (xio_waitingfor == siginfo->si_pid) {
|
||||||
xio_hashappened = true;
|
xio_hashappened = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue