Replaced SIGUSR1 with socketpair for synchronization between parent and child processes on RECVFROM type addresses

This commit is contained in:
Gerhard Rieger 2023-06-23 22:48:26 +02:00
parent a0e17a813a
commit 02483ff39e
12 changed files with 269 additions and 257 deletions

View file

@ -28,6 +28,13 @@ Coding:
Make gcc happy, replace strncat with "manual" copying Make gcc happy, replace strncat with "manual" copying
On addresses like UDP-RECVFROM with fork option every packet causes a
new child process which then reads the packet. The parent process must
wait until the packet has been read before checking again. The former
synchronization mechanism using SIGUSR1 is now replaced by a
socketpair. SIGUSR1 is no longer used for internal synchronization.
Tests: UDP4_FORK UDP6_FORK UNIX_FORK
####################### V 1.7.4.5 (not released): ####################### V 1.7.4.5 (not released):
Corrections: Corrections:

View file

@ -720,6 +720,7 @@ int socat(const char *address1, const char *address2) {
the communication channel, so continue */ the communication channel, so continue */
Info2("child "F_pid" has already died with status %d", Info2("child "F_pid" has already died with status %d",
XIO_RDSTREAM(sock1)->para.exec.pid, statunknown[i]); XIO_RDSTREAM(sock1)->para.exec.pid, statunknown[i]);
++num_child; /* it was counted as anonymous child, undo */
if (statunknown[i] != 0) { if (statunknown[i] != 0) {
return 1; return 1;
} }

278
test.sh
View file

@ -1935,7 +1935,7 @@ testaddrs () {
local a A; local a A;
for a in $@; do for a in $@; do
A=$(echo "$a" |tr 'a-z' 'A-Z') A=$(echo "$a" |tr 'a-z' 'A-Z')
if ! $SOCAT $A /dev/null 2>&1 |grep -q "E unknown device/address"; then if ! $SOCAT $A /dev/null 2>&1 </dev/null |grep -q "E unknown device/address"; then
shift shift
continue continue
fi fi
@ -1991,7 +1991,8 @@ childpids () {
AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;; AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;;
FreeBSD) l="$(ps -fl |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1)" |awk '{print($2);}')" ;; FreeBSD) l="$(ps -fl |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1)" |awk '{print($2);}')" ;;
HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; # Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
Linux) l="$(ps -fade |grep "^[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*$1 " |awk '{print($2);}')" ;;
# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)" |awk '{print($2);}')" ;; # NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)" |awk '{print($2);}')" ;;
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)" |awk '{print($2);}')" ;; NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)" |awk '{print($2);}')" ;;
OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
@ -5593,7 +5594,7 @@ N=$((N+1))
NAME=OUTBOUNDIN NAME=OUTBOUNDIN
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*) *%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%$NAME%*)
TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot" TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats openssl proxy); then elif ! feat=$(testfeats openssl proxy); then
@ -5684,7 +5685,7 @@ N=$((N+1))
#! #!
NAME=INTRANETRIPPER NAME=INTRANETRIPPER
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*) *%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%$NAME%*)
TEST="$NAME: gender changer via SSL through HTTP proxy, daemons" TEST="$NAME: gender changer via SSL through HTTP proxy, daemons"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats openssl proxy); then elif ! feat=$(testfeats openssl proxy); then
@ -5966,7 +5967,7 @@ testserversec () {
NAME=TCP4RANGEBITS NAME=TCP4RANGEBITS
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%fork%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option" TEST="$NAME: security of TCP4-L with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif [ -z "$SECONDADDR" ]; then elif [ -z "$SECONDADDR" ]; then
@ -5983,7 +5984,7 @@ N=$((N+1))
NAME=TCP4RANGEMASK NAME=TCP4RANGEMASK
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%fork%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option" TEST="$NAME: security of TCP4-L with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif [ -z "$SECONDADDR" ]; then elif [ -z "$SECONDADDR" ]; then
@ -6001,7 +6002,7 @@ N=$((N+1))
# like TCP4RANGEMASK, but the "bad" address is within the same class A network # like TCP4RANGEMASK, but the "bad" address is within the same class A network
NAME=TCP4RANGEMASKHAIRY NAME=TCP4RANGEMASKHAIRY
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option" TEST="$NAME: security of TCP4-L with RANGE option"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
newport tcp4 # provide free port number in $PORT newport tcp4 # provide free port number in $PORT
@ -6013,7 +6014,7 @@ N=$((N+1))
NAME=TCP4SOURCEPORT NAME=TCP4SOURCEPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with SOURCEPORT option" TEST="$NAME: security of TCP4-L with SOURCEPORT option"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
newport tcp4 # provide free port number in $PORT newport tcp4 # provide free port number in $PORT
@ -6024,7 +6025,7 @@ N=$((N+1))
NAME=TCP4LOWPORT NAME=TCP4LOWPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with LOWPORT option" TEST="$NAME: security of TCP4-L with LOWPORT option"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
newport tcp4 # provide free port number in $PORT newport tcp4 # provide free port number in $PORT
@ -6035,7 +6036,7 @@ N=$((N+1))
NAME=TCP4WRAPPERS_ADDR NAME=TCP4WRAPPERS_ADDR
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with TCPWRAP option" TEST="$NAME: security of TCP4-L with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
@ -6055,7 +6056,7 @@ N=$((N+1))
NAME=TCP4WRAPPERS_NAME NAME=TCP4WRAPPERS_NAME
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with TCPWRAP option" TEST="$NAME: security of TCP4-L with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
@ -6076,7 +6077,7 @@ N=$((N+1))
NAME=TCP6RANGE NAME=TCP6RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of TCP6-L with RANGE option" TEST="$NAME: security of TCP6-L with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@ -6092,7 +6093,7 @@ N=$((N+1))
NAME=TCP6SOURCEPORT NAME=TCP6SOURCEPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*)
TEST="$NAME: security of TCP6-L with SOURCEPORT option" TEST="$NAME: security of TCP6-L with SOURCEPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@ -6108,7 +6109,7 @@ N=$((N+1))
NAME=TCP6LOWPORT NAME=TCP6LOWPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*)
TEST="$NAME: security of TCP6-L with LOWPORT option" TEST="$NAME: security of TCP6-L with LOWPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@ -6124,7 +6125,7 @@ N=$((N+1))
NAME=TCP6TCPWRAP NAME=TCP6TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of TCP6-L with TCPWRAP option" TEST="$NAME: security of TCP6-L with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then
@ -6145,7 +6146,7 @@ N=$((N+1))
NAME=UDP4RANGE NAME=UDP4RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of UDP4-L with RANGE option" TEST="$NAME: security of UDP4-L with RANGE option"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
newport udp4 # provide free port number in $PORT newport udp4 # provide free port number in $PORT
@ -6200,7 +6201,7 @@ N=$((N+1))
NAME=UDP6RANGE NAME=UDP6RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of UDP6-L with RANGE option" TEST="$NAME: security of UDP6-L with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@ -6269,7 +6270,7 @@ N=$((N+1))
NAME=OPENSSLTCP4_RANGE NAME=OPENSSLTCP4_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option" TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6286,7 +6287,7 @@ N=$((N+1))
NAME=OPENSSLTCP4_SOURCEPORT NAME=OPENSSLTCP4_SOURCEPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
TEST="$NAME: security of SSL-L with SOURCEPORT option" TEST="$NAME: security of SSL-L with SOURCEPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6303,7 +6304,7 @@ N=$((N+1))
NAME=OPENSSLTCP4_LOWPORT NAME=OPENSSLTCP4_LOWPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*)
TEST="$NAME: security of SSL-L with LOWPORT option" TEST="$NAME: security of SSL-L with LOWPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6320,7 +6321,7 @@ N=$((N+1))
NAME=OPENSSLTCP4_TCPWRAP NAME=OPENSSLTCP4_TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of SSL-L with TCPWRAP option" TEST="$NAME: security of SSL-L with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip4 tcp libwrap openssl); then elif ! feat=$(testfeats ip4 tcp libwrap openssl); then
@ -6341,7 +6342,7 @@ N=$((N+1))
NAME=OPENSSLCERTSERVER NAME=OPENSSLCERTSERVER
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
TEST="$NAME: security of SSL-L with client certificate" TEST="$NAME: security of SSL-L with client certificate"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6359,7 +6360,7 @@ N=$((N+1))
NAME=OPENSSLCERTCLIENT NAME=OPENSSLCERTCLIENT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
TEST="$NAME: security of SSL with server certificate" TEST="$NAME: security of SSL with server certificate"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6378,7 +6379,7 @@ N=$((N+1))
NAME=OPENSSLTCP6_RANGE NAME=OPENSSLTCP6_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option" TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6399,7 +6400,7 @@ N=$((N+1))
NAME=OPENSSLTCP6_SOURCEPORT NAME=OPENSSLTCP6_SOURCEPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option" TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6420,7 +6421,7 @@ N=$((N+1))
NAME=OPENSSLTCP6_LOWPORT NAME=OPENSSLTCP6_LOWPORT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*)
TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option" TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -6441,7 +6442,7 @@ N=$((N+1))
NAME=OPENSSLTCP6_TCPWRAP NAME=OPENSSLTCP6_TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option" TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then
@ -6464,7 +6465,7 @@ N=$((N+1))
# test security with the openssl-commonname option on client side # test security with the openssl-commonname option on client side
NAME=OPENSSL_CN_CLIENT_SECURITY NAME=OPENSSL_CN_CLIENT_SECURITY
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
TEST="$NAME: security of client openssl-commonname option" TEST="$NAME: security of client openssl-commonname option"
# connect using non matching server name/address with commonname # connect using non matching server name/address with commonname
# options, this should succeed. Then without this option, should fail # options, this should succeed. Then without this option, should fail
@ -6515,7 +6516,7 @@ N=$((N+1))
NAME=OPENSSL_FIPS_SECURITY NAME=OPENSSL_FIPS_SECURITY
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
TEST="$NAME: OpenSSL restrictions by FIPS" TEST="$NAME: OpenSSL restrictions by FIPS"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! testfeats openssl >/dev/null; then elif ! testfeats openssl >/dev/null; then
@ -7108,7 +7109,12 @@ kill $pid0 2>/dev/null
wait wait
if ! diff "$tref" "$tf" >"$tdiff"; then if ! diff "$tref" "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n" $PRINTF "$FAILED\n"
cat "${te}0" "${te}1" "${te}2" echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2" >&2
cat "$tdiff" cat "$tdiff"
numFAIL=$((numFAIL+1)) numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N" listFAIL="$listFAIL $N"
@ -7908,7 +7914,7 @@ N=$((N+1))
NAME=UDP4RECVFROM_RANGE NAME=UDP4RECVFROM_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of UDP4-RECVFROM with RANGE option" TEST="$NAME: security of UDP4-RECVFROM with RANGE option"
newport udp4 # provide free port number in $PORT newport udp4 # provide free port number in $PORT
#testserversec "$N" "$TEST" "$opts" "UDP4-RECVFROM:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "UDP4-SENDTO:127.0.0.1:$PORT" 4 udp $PORT 0 #testserversec "$N" "$TEST" "$opts" "UDP4-RECVFROM:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "UDP4-SENDTO:127.0.0.1:$PORT" 4 udp $PORT 0
@ -7920,7 +7926,7 @@ N=$((N+1))
NAME=UDP4RECVFROM_TCPWRAP NAME=UDP4RECVFROM_TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option" TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip4 udp libwrap) || ! runsip4 >/dev/null; then elif ! feat=$(testfeats ip4 udp libwrap) || ! runsip4 >/dev/null; then
@ -8056,7 +8062,7 @@ N=$((N+1))
NAME=UDP6RECVFROM_RANGE NAME=UDP6RECVFROM_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of UDP6-RECVFROM with RANGE option" TEST="$NAME: security of UDP6-RECVFROM with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@ -8176,7 +8182,7 @@ N=$((N+1))
NAME=IP4RECVFROM_RANGE NAME=IP4RECVFROM_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*)
TEST="$NAME: security of IP4-RECVFROM with RANGE option" TEST="$NAME: security of IP4-RECVFROM with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then
@ -8198,7 +8204,7 @@ N=$((N+1))
NAME=IP4RECVFROM_TCPWRAP NAME=IP4RECVFROM_TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option" TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then
@ -8281,7 +8287,7 @@ N=$((N+1))
NAME=IP6RECVFROM_RANGE NAME=IP6RECVFROM_RANGE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*)
TEST="$NAME: security of IP6-RECVFROM with RANGE option" TEST="$NAME: security of IP6-RECVFROM with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip6 rawip && runsip6); then elif ! feat=$(testfeats ip6 rawip && runsip6); then
@ -8303,7 +8309,7 @@ N=$((N+1))
NAME=IP6RECVFROM_TCPWRAP NAME=IP6RECVFROM_TCPWRAP
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option" TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then
@ -8650,48 +8656,69 @@ N=$((N+1))
NAME=TCP4ENDCLOSE NAME=TCP4ENDCLOSE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
TEST="$NAME: end-close keeps TCP V4 socket open" TEST="$NAME: end-close keeps TCP V4 socket open"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
tf="$td/test$N.stdout" tf="$td/test$N.stdout"
te="$td/test$N.stderr" te="$td/test$N.stderr"
tdiff="$td/test$N.diff" tdiff="$td/test$N.diff"
newport tcp4; p0=$PORT
newport tcp4; p1=$PORT newport tcp4; p1=$PORT
newport tcp4; p2=$PORT da2a="$(date) $RANDOM"
da1a="$(date) $RANDOM" da2b="$(date) $RANDOM"
da1b="$(date) $RANDOM" CMD0="$TRACE $SOCAT -lp collector $opts -u TCP4-LISTEN:$p0,$REUSEADDR,bind=$LOCALHOST -"
CMD1="$TRACE $SOCAT $opts -u - TCP4-CONNECT:$LOCALHOST:$p1" CMD1="$TRACE $SOCAT -lp forker $opts -U TCP4:$LOCALHOST:$p0,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,$REUSEADDR,fork"
CMD="$TRACE $SOCAT $opts -U TCP4:$LOCALHOST:$p2,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,$REUSEADDR,fork" CMD2="$TRACE $SOCAT -lp client $opts -u - TCP4-CONNECT:$LOCALHOST:$p1"
CMD3="$TRACE $SOCAT $opts -u TCP4-LISTEN:$p2,$REUSEADDR,bind=$LOCALHOST -"
printf "test $F_n $TEST... " $N printf "test $F_n $TEST... " $N
$CMD3 >"$tf" 2>"${te}3" & $CMD0 >"${tf}0" 2>"${te}0" &
pid3=$! pid0=$!
waittcp4port $p2 1 waittcp4port $p0 1
$CMD 2>"${te}2" & $CMD1 2>"${te}1" &
pid2=$! pid1=$!
usleep $MICROS usleep $MICROS
waittcp4port $p1 1 waittcp4port $p1 1
echo "$da1a" |$CMD1 2>>"${te}1a" echo "$da2a" |$CMD2 2>>"${te}2a"
echo "$da1b" |$CMD1 2>>"${te}1b" rc2a=$?
echo "$da2b" |$CMD2 2>>"${te}2b"
rc2b=$?
sleep 1 sleep 1
kill "$pid3" "$pid2" 2>/dev/null kill "$pid0" "$pid1" 2>/dev/null
wait wait
if [ $? -ne 0 ]; then if [ $rc2a -ne 0 -o $rc2b -ne 0 ]; then
$PRINTF "$FAILED: $TRACE $SOCAT:\n" $PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD1 &" echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
echo "$CMD2" echo "$CMD2"
cat "${te}1a" "${te}1b" "${te}2" "${te}3" cat "${te}2a" >&2
echo "$CMD2"
cat "${te}2b" >&2
numFAIL=$((numFAIL+1)) numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N" listFAIL="$listFAIL $N"
elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then elif ! $ECHO "$da2a\n$da2b" |diff - "${tf}0" >"$tdiff"; then
$PRINTF "$FAILED\n" $PRINTF "$FAILED (diff)\n"
echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2a" >&2
echo "$CMD2"
cat "${te}2b" >&2
cat "$tdiff" cat "$tdiff"
cat "${te}1a" "${te}1b" "${te}2" "${te}3"
numFAIL=$((numFAIL+1)) numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N" listFAIL="$listFAIL $N"
else else
$PRINTF "$OK\n" $PRINTF "$OK\n"
if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2" "${te}3"; fi if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2a" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2b" >&2; fi
numOK=$((numOK+1)) numOK=$((numOK+1))
fi fi
fi ;; # NUMCOND fi ;; # NUMCOND
@ -8701,7 +8728,7 @@ N=$((N+1))
NAME=EXECENDCLOSE NAME=EXECENDCLOSE
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%exec%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%exec%*|*%$NAME%*)
TEST="$NAME: end-close keeps EXEC child running" TEST="$NAME: end-close keeps EXEC child running"
if ! eval $NUMCOND; then :; else if ! eval $NUMCOND; then :; else
tf="$td/test$N.stdout" tf="$td/test$N.stdout"
@ -9875,7 +9902,7 @@ N=$((N+1))
# process under some circumstances. # process under some circumstances.
NAME=EXECPTYKILL NAME=EXECPTYKILL
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%exec%*|*%pty%*|*%$NAME%*) *%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%exec%*|*%pty%*|*%$NAME%*)
TEST="$NAME: exec:...,pty explicitely kills sub process" TEST="$NAME: exec:...,pty explicitely kills sub process"
# we want to check if the exec'd sub process is killed in time # we want to check if the exec'd sub process is killed in time
# for this we have a shell script that generates a file after two seconds; # for this we have a shell script that generates a file after two seconds;
@ -10037,7 +10064,7 @@ N=$((N+1))
# zombies because the master process did not catch SIGCHLD # zombies because the master process did not catch SIGCHLD
NAME=UDP4LISTEN_SIGCHLD NAME=UDP4LISTEN_SIGCHLD
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%zombie%*|*%signal%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%ipapp%*|*%udp%*|*%zombie%*|*%signal%*|*%$NAME%*)
TEST="$NAME: test if UDP4-LISTEN child becomes zombie" TEST="$NAME: test if UDP4-LISTEN child becomes zombie"
# idea: run a udp-listen process with fork and -T. Connect once, so a sub # 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 # process is forked off. Make some transfer and wait until the -T timeout is
@ -10091,7 +10118,7 @@ N=$((N+1))
# zombies because the master process caught SIGCHLD but did not wait() # zombies because the master process caught SIGCHLD but did not wait()
NAME=UDP4RECVFROM_SIGCHLD NAME=UDP4RECVFROM_SIGCHLD
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%signal%*|*%$NAME%*) *%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%signal%*|*%$NAME%*)
TEST="$NAME: test if UDP4-RECVFROM child becomes zombie" TEST="$NAME: test if UDP4-RECVFROM child becomes zombie"
# idea: run a udp-recvfrom process with fork and -T. Send it one packet, so a # idea: run a udp-recvfrom process with fork and -T. Send it one packet, so a
# sub process is forked off. Make some transfer and wait until the -T timeout # sub process is forked off. Make some transfer and wait until the -T timeout
@ -10115,25 +10142,39 @@ rc2=$?
sleep 1 sleep 1
#read -p ">" #read -p ">"
l="$(childprocess $pid1)" l="$(childprocess $pid1)"
#echo "l=\"$l\""
kill $pid1 2>/dev/null; wait kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then if [ $rc2 -ne 0 ]; then
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numCANT=$((numCANT+1)) numCANT=$((numCANT+1))
listCANT="$listCANT $N" listCANT="$listCANT $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numCANT=$((numCANT+1)) numCANT=$((numCANT+1))
listCANT="$listCANT $N" listCANT="$listCANT $N"
elif $(isdefunct "$l"); then elif $(isdefunct "$l"); then
$PRINTF "$FAILED: $TRACE $SOCAT:\n" $PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD1 &" echo "$CMD1 &"
cat "${te}1" >&2
echo "$CMD2" echo "$CMD2"
cat "${te}2" >&2
cat "${te}1" "${te}2" cat "${te}1" "${te}2"
numFAIL=$((numFAIL+1)) numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N" listFAIL="$listFAIL $N"
else else
$PRINTF "$OK\n" $PRINTF "$OK\n"
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numOK=$((numOK+1)) numOK=$((numOK+1))
fi fi
fi ;; # NUMCOND fi ;; # NUMCOND
@ -10204,7 +10245,7 @@ N=$((N+1))
# child process. # child process.
NAME=UDP4RECVFROM_FORK NAME=UDP4RECVFROM_FORK
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: test if UDP4-RECVFROM handles more than one packet" TEST="$NAME: test if UDP4-RECVFROM handles more than one packet"
# idea: run a UDP4-RECVFROM process with fork and -T. Send it one packet; # idea: run a UDP4-RECVFROM process with fork and -T. Send it one packet;
# send it a second packet and check if this is processed properly. If yes, the # send it a second packet and check if this is processed properly. If yes, the
@ -11293,7 +11334,7 @@ N=$((N+1))
NAME=SOCKETRANGEMASK NAME=SOCKETRANGEMASK
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%security%*|*%fork%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of generic socket-listen with RANGE option" TEST="$NAME: security of generic socket-listen with RANGE option"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif [ -z "$SECONDADDR" ]; then elif [ -z "$SECONDADDR" ]; then
@ -11374,7 +11415,7 @@ N=$((N+1))
# Test the generic setsockopt option # Test the generic setsockopt option
NAME=SETSOCKOPT NAME=SETSOCKOPT
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
TEST="$NAME: test the setsockopt option" TEST="$NAME: test the setsockopt option"
# Set the TCP_MAXSEG (MSS) option with a reasonable value, this should succeed. # Set the TCP_MAXSEG (MSS) option with a reasonable value, this should succeed.
# The try again with TCP_MAXSEG=1, this fails at least on Linux. # The try again with TCP_MAXSEG=1, this fails at least on Linux.
@ -12104,7 +12145,7 @@ feat="$(tolower "$FEAT")"
# test the max-children option on really connection oriented sockets # test the max-children option on really connection oriented sockets
NAME=${KEYW}MAXCHILDREN NAME=${KEYW}MAXCHILDREN
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*)
TEST="$NAME: max-children option" TEST="$NAME: max-children option"
# start a listen process with max-children=1; connect with a client, let it # start a listen process with max-children=1; connect with a client, let it
# sleep some time before sending data; connect with second client that sends # sleep some time before sending data; connect with second client that sends
@ -12189,7 +12230,7 @@ proto="$(echo "$PROTO" |tr A-Z a-z)"
# test the max-children option on pseudo connected sockets # test the max-children option on pseudo connected sockets
NAME=${KEYW}MAXCHILDREN NAME=${KEYW}MAXCHILDREN
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%maxchildren%*|*%socket%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%socket%*|*%$NAME%*)
TEST="$NAME: max-children option" TEST="$NAME: max-children option"
# start a listen process with max-children=1; connect with a client, let it # start a listen process with max-children=1; connect with a client, let it
# send data and then sleep; connect with second client that wants to send # send data and then sleep; connect with second client that wants to send
@ -12550,7 +12591,7 @@ N=$((N+1))
# had a bug that converted a bit mask of 0 internally to 0xffffffff # had a bug that converted a bit mask of 0 internally to 0xffffffff
NAME=TCP4RANGE_0BITS NAME=TCP4RANGE_0BITS
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: correct evaluation of range mask 0" TEST="$NAME: correct evaluation of range mask 0"
if ! eval $NUMCOND; then :; if ! eval $NUMCOND; then :;
elif [ -z "$SECONDADDR" ]; then elif [ -z "$SECONDADDR" ]; then
@ -12999,7 +13040,7 @@ if [ "$addropts" = "." ]; then addropts=; fi
# $ADDR with fork removes the file system entry when the process is terminated # $ADDR with fork removes the file system entry when the process is terminated
NAME=${ADDR_}_REMOVE_FORK NAME=${ADDR_}_REMOVE_FORK
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) *%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%unix%*|*%socket%*|*%$NAME%*)
TEST="$NAME: $ADDR with fork removes socket entry when terminated during accept" TEST="$NAME: $ADDR with fork removes socket entry when terminated during accept"
# start a socat process with listening unix domain socket etc and option fork. # start a socat process with listening unix domain socket etc and option fork.
# Terminate the process and check if the file system socket entry still exists. # Terminate the process and check if the file system socket entry still exists.
@ -16069,6 +16110,101 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
while read KEYW FEAT RUNS ADDR IPPORT; do
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
RUNS=$(tolower $KEYW)
PROTO=$KEYW
proto="$(echo "$PROTO" |tr A-Z a-z)"
feat="$(tolower "$FEAT")"
# test the fork option on really RECVFROM oriented sockets
NAME=${KEYW}_FORK
case "$TESTS" in
*%$N%*|*%functions%*|*%fork%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*)
TEST="$NAME: ${KEYW}-RECVFROM with fork option"
# Start a RECVFROM process with fork option and SYSTEM address where clients
# data determines the sleep time; send a record with sleep before storing the
# data, then send a record with 0 sleep before storing data.
# When the second record is stored before the first one the test succeeded.
if ! eval $NUMCOND; then :;
elif ! F=$(testfeats $FEAT STDIO SYSTEM); then
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs - STDIO SYSTEM $PROTO-RECVFROM $PROTO-SENDTO); then
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! o=$(testoptions fork ) >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runs$RUNS >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}$(toupper $RUNS) not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
else
case "X$IPPORT" in
"XPORT")
newport $proto
tsl=$PORT # test socket listen address
tsc="$ADDR:$PORT" # test socket connect address
;;
*)
tsl="$(eval echo "$ADDR")" # resolve $N
tsc=$tsl
esac
#ts="$td/test$N.sock"
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
CMD0="$TRACE $SOCAT $opts -t 3 $PROTO-RECVFROM:$tsl,fork SYSTEM:'read t x; sleep \$t; echo \$x >>'\"$tf\""
CMD1="$TRACE $SOCAT $opts -t 3 - $PROTO-SENDTO:$tsc"
printf "test $F_n $TEST... " $N
eval $CMD0 </dev/null 2>"${te}0" &
pid0=$!
wait${proto}port $tsl 1
echo "2 $da 1" |$CMD1 >"${tf}1" 2>"${te}1" &
pid1=$!
sleep 1
echo "0 $da 2" |$CMD1 >"${tf}2" 2>"${te}2" &
pid2=$!
sleep 2
cpids="$(childpids $pid0 </dev/null)"
kill $pid1 $pid2 $cpids $pid0 2>/dev/null; wait
if echo -e "$da 2\n$da 1" |diff - $tf >$tdiff; then
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2" >&2
echo "diff:" >&2
cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
fi
fi # NUMCOND
;;
esac
N=$((N+1))
done <<<"
UDP4 UDP udp4 127.0.0.1 PORT
UDP6 UDP udp4 [::1] PORT
UNIX unix unix $td/test\$N.server -
"
# end of common tests # end of common tests
################################################################################## ##################################################################################

View file

@ -338,11 +338,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
pid_t pid; /* mostly int; only used with fork */ pid_t pid; /* mostly int; only used with fork */
sigset_t mask_sigchld; sigset_t mask_sigchld;
/* we must prevent that the current packet triggers another fork; /* Block SIGCHLD until parent is ready to react */
therefore we wait for a signal from the recent child: USR1
indicates that is has consumed the last packet; CHLD means it has
terminated */
/* block SIGCHLD and SIGUSR1 until parent is ready to react */
sigemptyset(&mask_sigchld); sigemptyset(&mask_sigchld);
sigaddset(&mask_sigchld, SIGCHLD); sigaddset(&mask_sigchld, SIGCHLD);
Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL); Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL);
@ -383,6 +379,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
/* now we are ready to handle signals */ /* now we are ready to handle signals */
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL); Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
while (maxchildren) { while (maxchildren) {
if (num_child < maxchildren) break; if (num_child < maxchildren) break;
Notice("maxchildren are active, waiting"); Notice("maxchildren are active, waiting");

View file

@ -545,7 +545,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
applyopts(fdi, *copts, PH_LATE2); applyopts(fdi, *copts, PH_LATE2);
} }
if (withfork) { if (withfork) {
Info("Signalling parent ready"); Info("notifying parent that child process is ready");
Close(trigger[1]); /* in child, notify parent that ready */ Close(trigger[1]); /* in child, notify parent that ready */
} }
} /* withfork */ } /* withfork */
@ -603,7 +603,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
fds[0].fd = trigger[0]; fds[0].fd = trigger[0];
fds[0].events = POLLIN|POLLHUP; fds[0].events = POLLIN|POLLHUP;
Poll(fds, 1, -1); Poll(fds, 1, -1);
Info("Child process signalled ready"); Info("child process notified parent that it is ready");
} }
return pid; /* indicate parent (main) process */ return pid; /* indicate parent (main) process */

View file

@ -1084,101 +1084,13 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
packet in the IP stacks input queue and forks a sub process. The sub process packet in the IP stacks input queue and forks a sub process. The sub process
then reads this packet for processing its data. then reads this packet for processing its data.
There is a problem because the parent process would find the same packet There is a problem because the parent process would find the same packet
again if it calls select()/poll() before the child process reads the again if it calls select()/poll() before the child process has read the
packet. packet.
To solve this problem we implement the following mechanism: To solve this problem we implement the following mechanism:
The sub process sends a SIGUSR1 when it has read the packet (or a SIGCHLD if Before forking an unnamed pipe (fifo) is created. The sub process closes the
it dies before). The parent process waits until it receives that signal and write side when it has read the packet. The parent process waits until the
only then continues to listen. read side of the pipe gives EOF and only then continues to listen.
To prevent a signal from another process to trigger our loop, we pass the
pid of the sub process to the signal handler in xio_waitingfor. The signal
handler sets xio_hashappened if the pid matched.
*/ */
static pid_t xio_waitingfor; /* info from recv loop to signal handler:
indicates the pid of the child process
that should send us the USR1 signal */
static bool xio_hashappened; /* info from signal handler to loop: child
process has read ("consumed") the packet */
static int xio_childstatus;
/* this is the signal handler for USR1 and CHLD */
void xiosigaction_hasread(int signum
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
, siginfo_t *siginfo, void *ucontext
#endif
) {
pid_t pid;
int _errno;
int status = 0;
bool wassig = false;
_errno = errno;
diag_in_handler = 1;
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
siginfo->si_pid);
#else
Debug1("xiosigaction_hasread(%d)", signum);
#endif
if (signum == SIGCHLD) {
do {
pid = Waitpid(-1, &status, WNOHANG);
if (pid == 0) {
Msg(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): no child has exited");
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
} else if (pid < 0 && errno == EINTR) {
Info1("xiosigaction_hasread(): %s", strerror(errno));
} else if (pid < 0 && errno == ECHILD) {
Msg(wassig?E_INFO:E_NOTICE,
"waitpid(-1, {}, WNOHANG): "F_strerror);
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
wassig = true;
if (pid < 0) {
Warn1("waitpid(-1, {%d}, WNOHANG): "F_strerror, status);
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
if (pid == xio_waitingfor) {
xio_waitingfor = 0; /* so this child will not set hashappened again */
xio_hashappened = true;
xio_childstatus = WEXITSTATUS(status);
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
} while (1);
}
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
if (xio_waitingfor == siginfo->si_pid) {
xio_hashappened = true;
}
#else
xio_hashappened = true;
#endif
#if !HAVE_SIGACTION
Signal(sig, xiosigaction_hasread);
#endif /* !HAVE_SIGACTION */
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
/* waits for incoming packet, checks its source address and port. Depending /* waits for incoming packet, checks its source address and port. Depending
on fork option, it may fork a subprocess. on fork option, it may fork a subprocess.
@ -1267,42 +1179,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
} }
if (dofork) { if (dofork) {
#if HAVE_SIGACTION xiosetchilddied();
{
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/
#ifdef SA_SIGINFO /* not on Linux 2.0(.33) */
|SA_SIGINFO
#endif
#ifdef SA_NOMASK
|SA_NOMASK
#endif
;
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
act.sa_sigaction = xiosigaction_hasread;
#else /* Linux 2.0(.33) does not have sigaction.sa_sigaction */
act.sa_handler = xiosigaction_hasread;
#endif
sigfillset(&act.sa_mask);
if (Sigaction(SIGUSR1, &act, NULL) < 0) {
/*! Linux man does not explicitely say that errno is defined */
Warn1("sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
}
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
/*! Linux man does not explicitely say that errno is defined */
Warn1("sigaction(SIGCHLD, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
}
}
#else /* !HAVE_SIGACTION */
/*!!!*/
if (Signal(SIGUSR1, xiosigaction_hasread) == SIG_ERR) {
Warn1("signal(SIGUSR1, xiosigaction_hasread): %s", strerror(errno));
}
if (Signal(SIGCHLD, xiosigaction_hasread) == SIG_ERR) {
Warn1("signal(SIGCHLD, xiosigaction_hasread): %s", strerror(errno));
}
#endif /* !HAVE_SIGACTION */
} }
while (true) { /* but we only loop if fork option is set */ while (true) { /* but we only loop if fork option is set */
@ -1314,6 +1191,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
socklen_t palen = sizeof(_peername); /* peer address size */ socklen_t palen = sizeof(_peername); /* peer address size */
char ctrlbuff[1024]; /* ancillary messages */ char ctrlbuff[1024]; /* ancillary messages */
struct msghdr msgh = {0}; struct msghdr msgh = {0};
int trigger[2]; /* for socketpair that indicates consumption of packet */
int rc; int rc;
socket_init(pf, pa); socket_init(pf, pa);
@ -1397,29 +1275,22 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
xfd->salen = palen; xfd->salen = palen;
if (dofork) { if (dofork) {
sigset_t oldset, mask_sigchldusr1; Info("Generating socketpair that triggers parent when packet has been consumed");
if (Socketpair(PF_UNIX, SOCK_STREAM, 0, trigger) < 0) {
/* we must prevent that the current packet triggers another fork; Error1("socketpair(PF_UNIX, SOCK_STREAM, 0, ...): %s", strerror(errno));
therefore we wait for a signal from the recent child: USR1 }
indicates that is has consumed the last packet; CHLD means it has
terminated */
/* block SIGCHLD and SIGUSR1 until parent is ready to react */
Sigprocmask(SIG_BLOCK, NULL, &mask_sigchldusr1);
sigaddset(&mask_sigchldusr1, SIGCHLD);
sigaddset(&mask_sigchldusr1, SIGUSR1);
Sigprocmask(SIG_SETMASK, &mask_sigchldusr1, &oldset);
if ((pid = xio_fork(false, level)) < 0) { if ((pid = xio_fork(false, level)) < 0) {
Close(trigger[0]);
Close(trigger[1]);
Close(xfd->fd); Close(xfd->fd);
Sigprocmask(SIG_SETMASK, &oldset, NULL);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (pid == 0) { /* child */ if (pid == 0) { /* child */
/* no reason to block SIGCHLD in child process */ Close(trigger[0]);
Sigprocmask(SIG_SETMASK, &oldset, NULL); xfd->triggerfd = trigger[1];
xfd->ppid = Getppid(); /* send parent a signal when packet has Fcntl_l(xfd->triggerfd, F_SETFD, FD_CLOEXEC);
been consumed */
#if WITH_RETRY #if WITH_RETRY
/* !? */ /* !? */
@ -1437,29 +1308,14 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
break; break;
} }
xio_waitingfor = pid; /* Parent */
Close(trigger[1]);
do {
#if HAVE_PSELECT
{ {
struct timespec timeout = { LONG_MAX, 0 }; char buf[1];
Pselect(0, NULL, NULL, NULL, &timeout, &oldset); while (Read(trigger[0], buf, 1) < 0 && errno == EINTR) ;
Sigprocmask(SIG_SETMASK, &oldset, NULL);
} }
#else /* ! HAVE_PSELECT */
/* now we are ready to handle signals */
Sigprocmask(SIG_SETMASK, &oldset, NULL);
Sleep(1); /* any signal speeds up return */
#endif /* ! HAVE_PSELECT */
} while (!xio_hashappened) ;
xio_hashappened = false;
if (xio_childstatus != 0) {
char buff[512];
Recv(xfd->fd, buff, sizeof(buff), 0);
xio_childstatus = 0;
Info("drop data because of child exit failed");
}
Info("continue listening"); Info("continue listening");
} else { } else {
break; break;

View file

@ -226,7 +226,9 @@ int _xioopen_ipdgram_listen(struct single *sfd,
} }
/* server: continue loop with socket()+recvfrom() */ /* server: continue loop with socket()+recvfrom() */
/* when we dont close this we get awkward behaviour on Linux 2.4: /* This avoids the requirement of a sync (trigger) mechanism as with
RECVFROM addresses */
/* And when we dont close this we got awkward behaviour on Linux 2.4:
recvfrom gives 0 bytes with invalid socket address */ recvfrom gives 0 bytes with invalid socket address */
if (Close(sfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", sfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));

6
xio.h
View file

@ -164,6 +164,7 @@ typedef struct single {
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/ size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
xiolock_t lock; /* parameters of lockfile */ xiolock_t lock; /* parameters of lockfile */
bool havelock; /* we are happy owner of the above lock */ bool havelock; /* we are happy owner of the above lock */
int triggerfd; /* close this FD in child process to signal parent */
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */ bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
/* until here, keep consistent with bipipe.dual ! */ /* until here, keep consistent with bipipe.dual ! */
int argc; /* number of fields in argv */ int argc; /* number of fields in argv */
@ -199,7 +200,6 @@ typedef struct single {
struct termios savetty; /* save orig tty settings for later restore */ struct termios savetty; /* save orig tty settings for later restore */
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
int (*sigchild)(struct single *); /* callback after sigchild */ int (*sigchild)(struct single *); /* callback after sigchild */
pid_t ppid; /* parent pid, only if we send it signals */
int escape; /* escape character; -1 for no escape */ int escape; /* escape character; -1 for no escape */
bool actescape; /* escape character found in input data */ bool actescape; /* escape character found in input data */
union { union {
@ -312,7 +312,9 @@ typedef union bipipe {
size_t actbytes; /* so many bytes still to be read */ size_t actbytes; /* so many bytes still to be read */
xiolock_t lock; /* parameters of lockfile */ xiolock_t lock; /* parameters of lockfile */
bool havelock; /* we are happy owner of the above lock */ bool havelock; /* we are happy owner of the above lock */
xiosingle_t *stream[2]; /* input stream, output stream */ int triggerfd; /* close this FD in child process to notify parent */
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
struct single *stream[2]; /* input stream, output stream */
} dual; } dual;
} xiofile_t; } xiofile_t;

View file

@ -217,6 +217,15 @@ pid_t xio_fork(bool subchild, int level) {
if (!subchild) { if (!subchild) {
/* set SOCAT_PID to new value */ /* set SOCAT_PID to new value */
xiosetenvulong("PID", pid, 1); xiosetenvulong("PID", pid, 1);
} else {
/* Make sure the sub process does not hold the trigger pipe open */
if (sock1 != NULL) {
struct single *sfd;
sfd = XIO_RDSTREAM(sock1);
if (sfd->triggerfd >= 0) Close(sfd->triggerfd);
sfd = XIO_WRSTREAM(sock1);
if (sfd->triggerfd >= 0) Close(sfd->triggerfd);
}
} }
/* gdb recommends to have env controlled sleep after fork */ /* gdb recommends to have env controlled sleep after fork */
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) { if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {

View file

@ -363,7 +363,7 @@ static xiofile_t *xioallocfd(void) {
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
/* fd->common.ignoreeof = false; */ /* fd->common.ignoreeof = false; */
/* fd->common.eof = 0; */ /* fd->common.eof = 0; */
fd->stream.triggerfd = -1;
fd->stream.fd = -1; fd->stream.fd = -1;
fd->stream.dtype = XIODATA_STREAM; fd->stream.dtype = XIODATA_STREAM;
#if _WITH_SOCKET #if _WITH_SOCKET

View file

@ -271,8 +271,10 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
#else #else
Shutdown(pipe->fd, SHUT_RD); Shutdown(pipe->fd, SHUT_RD);
#endif #endif
if (pipe->ppid > 0) { if (pipe->triggerfd >= 0) {
Kill(pipe->ppid, SIGUSR1); Info("notifying parent that socket is ready again");
Close(pipe->triggerfd);
pipe->triggerfd = -1;
} }
} }

View file

@ -112,7 +112,6 @@ void childdied(int signum) {
return; return;
} }
/*! indent */ /*! indent */
if (num_child) num_child--;
/* check if it was a registered child process */ /* check if it was a registered child process */
i = 0; i = 0;
while (i < XIO_MAXSOCK) { while (i < XIO_MAXSOCK) {
@ -121,6 +120,7 @@ void childdied(int signum) {
} }
if (i == XIO_MAXSOCK) { if (i == XIO_MAXSOCK) {
Info2("childdied(%d): cannot identify child %d", signum, pid); Info2("childdied(%d): cannot identify child %d", signum, pid);
if (num_child) num_child--;
if (nextunknown == NUMUNKNOWN) { if (nextunknown == NUMUNKNOWN) {
nextunknown = 0; nextunknown = 0;
} }