[issue895] pselect(2) implementation

Nicolas Thery sinknull at crater.dragonflybsd.org
Wed Dec 26 10:18:52 PST 2007


Nicolas Thery <nthery at gmail.com> added the comment:

Attached test suite.

----------
status: unread -> chatting

_____________________________________________________
DragonFly issue tracker <bugs at lists.dragonflybsd.org>
<http://bugs.dragonflybsd.org/issue895>
_____________________________________________________/*
 * Rudimentary test suite used while implementing pselect(2).
 */

#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


static int alarm_flag = 0;


static void
nop(int signo)
{
}


static void
set_alarm_flag(int signo)
{
	alarm_flag = 1;
}


/*
 * Try to detect regressions in select(2).
 */

static void
test_select()
{
	fd_set rset;
	fd_set wset;
	struct timeval timeout;
	int des[2];
	int r;
	char buf[1];

	printf("test_select\n");

	/*
	 * It is always possible to write to stdout (if not redirected).
	 */

	FD_ZERO(&wset);
	FD_SET(1, &wset);

	r = select(2, NULL, &wset, NULL, NULL);
	assert(r == 1);
	assert(FD_ISSET(1, &wset));

	/*
	 * Write to a pipe and check a select on the read end does not block.
	 */

	r = pipe(des);
	assert(r == 0);

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	buf[0] = 'f';
	r = write(des[1], buf, 1);
	assert(r == 1);

	r = select(des[0]+1, &rset, NULL, NULL, NULL);
	assert(r == 1);
	assert(FD_ISSET(des[0], &rset));

	r = read(des[0], buf, 1);
	assert(r == 1);
	assert(buf[0] == 'f');

	/*
	 * Block until signal reception.
	 */

	signal(SIGALRM, nop);
	alarm(1);

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	r = select(des[0]+1, &rset, NULL, NULL, NULL);
	assert(r == -1);
	assert(errno == EINTR);

	/*
	 * Block until timeout.
	 */

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	timeout.tv_sec = 1;
	timeout.tv_usec = 0;
	r = select(des[0]+1, &rset, NULL, NULL, &timeout);
	assert(r == 0);

	/*
	 * When the timeout is zero, the call should not block.
	 */

	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	r = select(des[0]+1, &rset, NULL, NULL, &timeout);
	assert(r == 0);

	close(des[0]);
	close(des[1]);
}


/*
 * Very roughly exercise pselect(2).
 */

static void
test_pselect()
{
	fd_set rset;
	fd_set wset;
	sigset_t blockset;
	struct timespec timeout;
	int des[2];
	int r;
	char buf[1];

	printf("test_pselect\n");

	/*
	 * It is always possible to write to stdout (if not redirected).
	 */

	FD_ZERO(&wset);
	FD_SET(1, &wset);

	r = pselect(2, NULL, &wset, NULL, NULL, NULL);
	assert(r == 1);
	assert(FD_ISSET(1, &wset));

	/*
	 * Write to a pipe and check a select on the read end does not block.
	 */

	r = pipe(des);
	assert(r == 0);

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	buf[0] = 'f';
	r = write(des[1], buf, 1);
	assert(r == 1);

	r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
	assert(r == 1);
	assert(FD_ISSET(des[0], &rset));

	r = read(des[0], buf, 1);
	assert(r == 1);
	assert(buf[0] == 'f');

	/*
	 * Block until signal reception.
	 */

	signal(SIGALRM, nop);
	alarm(1);

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
	assert(r == -1);
	assert(errno == EINTR);

	/*
	 * Block until timeout.
	 */

	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	timeout.tv_sec = 1;
	timeout.tv_nsec = 0;
	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
	assert(r == 0);

	/*
	 * When the timeout is zero, the call should not block.
	 */

	timeout.tv_sec = 0;
	timeout.tv_nsec = 0;
	FD_ZERO(&rset);
	FD_SET(des[0], &rset);

	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
	assert(r == 0);

	/*
	 * When a signal is masked, the syscall is not interrupted and the
	 * signal is received on completion.
	 */

	sigemptyset(&blockset);
	sigaddset(&blockset, SIGALRM);
	
	signal(SIGALRM, set_alarm_flag);
	alarm(1);

	timeout.tv_sec = 2;
	timeout.tv_nsec = 0;
	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset);
	assert(r == 0);
	assert(alarm_flag);

	close(des[0]);
	close(des[1]);
}


int
main(void)
{
	test_select();
	test_pselect();
	return (0);
}




More information about the Bugs mailing list