so_rcv_sx, deadlkres, SIGSTOP

Jilles Tjoelker jilles at stack.nl
Sun Apr 4 20:40:58 UTC 2010


On Sun, Apr 04, 2010 at 09:12:33PM +0300, Kostik Belousov wrote:
> On Sun, Apr 04, 2010 at 07:51:40PM +0200, Jilles Tjoelker wrote:
> > The SX locks so_snd_sx and so_rcv_sx can be legitimately held for
> > arbitrary amounts of time, while waiting until a send or recv is
> > possible. Any other threads wanting to send/recv on the socket will
> > sleep interruptibly on the corresponding SX. If deadlkres is activated,
> > it may detect a deadlock even though there is no problem.

> > If a SIGSTOP or similar comes in while waiting until send/recv is
> > possible, the SX is held across the suspension and noone will be able to
> > send/recv on the socket until the process is resumed. On the other hand
> > a thread waiting for the SX can be suspended without harm. Adding PBDRY
> > to various sleeps may help but may also introduce other problems
> > (SIGSTOP disturbing the functioning of the process more, possibly with
> > stuff like SO_RCVTIMEO).
> Could you, please, elaborate on this (interaction between PBDRY and some
> socket timeout stuff) ?

A SIGSTOP will currently not affect a SO_RCVTIMEO timeout, just like it
does not affect a nanosleep(2).

Demonstration is analogous to my earlier example with /bin/sleep,
where ./socktimeout is the program below:

% /usr/bin/time ./socktimeout
^Z
% fg   # such that the program can run again 10 seconds after starting
socktimeout: read: Resource temporarily unavailable
       10.00 real         0.00 user         0.00 sys
%

PBDRY would cause an immediate Interrupted system call return.

I don't know how much SO_RCVTIMEO/SO_SNDTIMEO are used (a POSIX
application cannot rely on their support for any kind of socket), and it
is likely applications using it can already get EINTR from signal
handlers.

#include	<sys/socket.h>
#include	<err.h>
#include	<errno.h>
#include	<stdio.h>
#include	<time.h>
#include	<unistd.h>

int
main(int argc, char *argv[])
{
	int sock;

	sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
	if (sock == -1)
		err(1, "socket");
	if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
	    &(const struct timeval){ 10, 0 }, sizeof(struct timeval)) == -1)
		err(1, "setsockopt(SO_RCVTIMEO)");
	errno = 0;
	if (read(sock, (char[]){ 0 }, 1) != 1)
		err(1, "read");

	return 0;
}

-- 
Jilles Tjoelker


More information about the freebsd-arch mailing list