mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Prevent error loop on RECVFROM addresses with fork
This commit is contained in:
parent
10680c8aad
commit
ff8de6c5cd
3 changed files with 27 additions and 3 deletions
7
CHANGES
7
CHANGES
|
@ -43,6 +43,13 @@ Corrections:
|
|||
is now increased to 2047 bytes.
|
||||
Change suggested by Mario Camou.
|
||||
|
||||
Addresses of type RECVFROM with option fork looped with an error
|
||||
message in case that the second address failed before consuming the
|
||||
packet. The fix makes RECVFROM drop the packet when the second address
|
||||
failed before reading it. Use retry or forever option with the second
|
||||
address if you want to avoid data loss.
|
||||
Thanks to Chunmei Xu for reporting this issue and proving the patch.
|
||||
|
||||
Porting:
|
||||
In gcc version 10 the default changed from -fcommon to -fno-common.
|
||||
Consequently, linking filan and procan failed with error
|
||||
|
|
14
doc/socat.yo
14
doc/socat.yo
|
@ -419,6 +419,7 @@ label(ADDRESS_IP_RECVFROM)dit(bf(tt(IP-RECVFROM:<protocol>)))
|
|||
This address works well with IP-SENDTO address peers (see above).
|
||||
Protocol 255 uses the raw socket with the IP header being part of the
|
||||
data.nl()
|
||||
See the link(note about RECVFROM addresses)(NOTE_RECVFROM).nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
|
||||
Useful options:
|
||||
link(pf)(OPTION_PROTOCOL_FAMILY),
|
||||
|
@ -790,6 +791,7 @@ label(ADDRESS_SOCKET_RECVFROM)dit(bf(tt(SOCKET-RECVFROM:<domain>:<type>:<protoco
|
|||
to find the appropriate values. The local-address must be the
|
||||
link(data)(TYPE_DATA) representation of a sockaddr structure without
|
||||
sa_family and (BSD) sa_len components.nl()
|
||||
See the link(note about RECVFROM addresses)(NOTE_RECVFROM).nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)nl()
|
||||
Useful options:
|
||||
link(fork)(OPTION_FORK),
|
||||
|
@ -1113,11 +1115,15 @@ label(ADDRESS_UDP_RECVFROM)dit(bf(tt(UDP-RECVFROM:<port>)))
|
|||
UDP/IP version 4 or 6
|
||||
depending on option link(pf)(OPTION_PROTOCOL_FAMILY).
|
||||
It receives one packet from an unspecified peer and may send one or more
|
||||
answer packets to that peer. This mode is particularly useful with fork
|
||||
option
|
||||
answer packets to that peer. This mode is particularly useful with
|
||||
link(fork)(OPTION_FORK) option
|
||||
where each arriving packet - from arbitrary peers - is handled by its own sub
|
||||
process. This allows a behaviour similar to typical UDP based servers like ntpd
|
||||
or named. This address works well with socat UDP-SENDTO address peers.nl()
|
||||
label(NOTE_RECVFROM)Note: When the second address fails before entering the transfer loop the
|
||||
packet is dropped. Use option link(retry)(OPTION_RETRY) or
|
||||
link(forever)(OPTION_FOREVER) on the second address to avoid data loss.
|
||||
nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
|
||||
Useful options:
|
||||
link(fork)(OPTION_FORK),
|
||||
|
@ -1233,6 +1239,7 @@ label(ADDRESS_UNIX_RECVFROM)dit(bf(tt(UNIX-RECVFROM:<filename>)))
|
|||
This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process.
|
||||
This address works well with socat UNIX-SENDTO address peers.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(CHILD)(GROUP_CHILD),link(UNIX)(GROUP_SOCK_UNIX) nl()
|
||||
See the link(note about RECVFROM addresses)(NOTE_RECVFROM).nl()
|
||||
Useful options:
|
||||
link(fork)(OPTION_FORK)nl()
|
||||
See also:
|
||||
|
@ -2310,7 +2317,8 @@ label(OPTION_FORK)dit(bf(tt(fork)))
|
|||
child:
|
||||
OPENSSL-LISTEN forks em(before) the SSL handshake, while OPENSSL-CONNECT
|
||||
forks em(afterwards).
|
||||
RETRY and FOREVER options are not inherited by the child process.nl()
|
||||
link(retry)(OPTION_RETRY) and link(forever)(OPTION_FOREVER) options are not
|
||||
inherited by the child process.nl()
|
||||
On some operating systems (e.g. FreeBSD) this option does not work for
|
||||
UDP-LISTEN addresses.nl()
|
||||
enddit()
|
||||
|
|
|
@ -1128,6 +1128,8 @@ static pid_t xio_waitingfor; /* info from recv loop to signal handler:
|
|||
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)
|
||||
|
@ -1179,6 +1181,7 @@ void xiosigaction_hasread(int signum
|
|||
}
|
||||
if (pid == xio_waitingfor) {
|
||||
xio_hashappened = true;
|
||||
xio_childstatus = WEXITSTATUS(status);
|
||||
Debug("xiosigaction_hasread() ->");
|
||||
diag_in_handler = 0;
|
||||
errno = _errno;
|
||||
|
@ -1480,6 +1483,12 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
xio_waitingfor = 0; /* so this child will not set hashappened again */
|
||||
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");
|
||||
} else {
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue