[net.bugs.4bsd] interrupted select

mogul@Gregorio.ARPA (05/14/85)

Index:	sys/sys/sys_generic.c 4.2BSD

Description:
	If select() is called with a null pointer for the "timeout"
	argument, and then interrupted, it fails to modify the
	bit mask arguments, thus implying that all descriptors
	are ready (although they may not be).
	
	If the timeout argument is specified, select() behaves the
	way one would expect, setting all the masks to zero before
	returning.

	This inconsistency is not documented.  To be fair to the
	implementer, neither the manual page nor the "4.2 System
	Manual" specifies what select() should do when it is
	interrupted.

Repeat-By:
	Run this program:

	#include <sys/time.h>
	#include <signal.h>

	catcher(){}

	main()
	{
		struct timeval tv;
		int fd;

		signal(SIGALRM, catcher);
		fd = 1;
		tv.tv_sec = 10; tv.tv_usec = 0;
		alarm(2);
		select(1, &fd, 0, 0, &tv);
		printf("with tv: %d\n", fd);	

		signal(SIGALRM, catcher);
		fd = 1;
		alarm(2);
		select(1, &fd, 0, 0, 0);
		printf("no tv: %d\n", fd);	
	}

	It prints:
	
	with tv: 0
	no tv: 1

Suggested Fix (untested!):
	In the select() function in sys/sys/sys_generic.c, some
	attempt is made to clean up after an interrupt IF a
	timeout is specified.  A similar clean-up should be
	done even if no timeout is specified.
	
	I don't feel like trying to test this fix, since I
	have a workaround in my program.  However, I believe
	this version of the code (between the "lqsave = u.u_qsave"
	and the "splx(s)" of the original code) should work.

	lqsave = u.u_qsave;
	if (setjmp(&u.u_qsave)) {
		if (uap->tv)
			untimeout(unselect, (caddr_t)u.u_procp);
		u.u_error = EINTR;
		splx(s);
		goto done;
	}
	if (uap->tv)
		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
	sleep((caddr_t)&selwait, PZERO+1);
	u.u_qsave = lqsave;
	if (uap->tv)
		untimeout(unselect, (caddr_t)u.u_procp);
	splx(s);

matt@oddjob.UUCP (Matt Crawford) (05/17/85)

In article <163@Gregorio.ARPA> mogul@Gregorio.ARPA writes:
>
>Description:
>	If select() is called with a null pointer for the "timeout"
>	argument, and then interrupted, it fails to modify the
>	bit mask arguments, thus implying that all descriptors
>	are ready (although they may not be).
>	....

If you do not test the return value of select() your program is wrong.
Only use the mask values if the return value is strictly greater than 0.
The manual page says that it is a bug that the masks are ever modified
when select times out.  The same comment should also be made about
interrupts.  In fact, the pyramid does not have this bug.  
_____________________________________________________
Matt		University	crawford@anl-mcs.arpa
Crawford	of Chicago	ihnp4!oddjob!matt