fixed a bug where sub processes would become zombies because the master process caught SIGCHLD but did not wait()

This commit is contained in:
Gerhard Rieger 2008-02-01 23:38:16 +01:00
parent 1f5165b765
commit 3b3b004ff8
4 changed files with 84 additions and 1 deletions

View file

@ -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

View file

@ -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
View file

@ -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

View file

@ -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;
} }