tst-cancel4 fails at pselect
Ingo Brueckl
ib@wupperonline.de
Mon Apr 5 21:51:00 GMT 2010
In order to track down the problem, I created a test program that calls both
select() and pselect() either directly or by creating a thread. Only if
pselect() is used and called within a thread, it mysteriously returns (most
often).
Can somebody confirm, report different result or explain what is going wrong
here? pselect() should wait forever and be cancelled after the nanosleep!
$ ./test 1
Test #1, with select, direct call
calling now
^C (cancelled by me)
$ ./test 2
Test #2, with select and thread
creating thread
cancelling thread
end of test
$ ./test 3
Test #3, with pselect, direct call
calling now
^C (cancelled by me)
$ ./test 4
Test #4, with pselect and thread
creating thread
Oops! pselect returned with 0 <-- this is mystery
$ ./test 4
Test #4, with pselect and thread <-- sometimes it works
creating thread
cancelling thread
end of test
The program:
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
static int fds[2];
static void *test (void *arg)
{
char *what;
int ret;
fd_set rfs;
FD_ZERO(&rfs);
FD_SET(fds[0], &rfs);
if (*(char *) arg == '1' || *(char *) arg == '2')
{
what = "select";
ret = select(fds[0] + 1, &rfs, NULL, NULL, NULL);
}
else
{
what = "pselect";
ret = pselect(fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
}
printf("Oops! %s returned with %d\n", what, ret);
_exit(1);
}
int main (int argc, char **argv)
{
pthread_t th;
int thread = (*argv[1] == '2' || *argv[1] == '4');
printf("Test #%c, ", *argv[1]);
switch (*argv[1])
{
case '1':
printf("with select, direct call\n");
break;
case '2':
printf("with select and thread\n");
break;
case '3':
printf("with pselect, direct call\n");
break;
case '4':
printf("with pselect and thread\n");
break;
}
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, fds) != 0)
{
perror ("socketpair");
return 1;
}
if (thread)
{
puts(" creating thread");
if (pthread_create (&th, NULL, test, argv[1]) != 0)
{
perror("create thread");
return 1;
}
}
else
{
puts(" calling now");
test(argv[1]);
}
struct timespec ts = {.tv_sec = 3, .tv_nsec = 0};
while (nanosleep(&ts, &ts) != 0) continue;
if (thread)
{
puts(" cancelling thread");
if (pthread_cancel(th) != 0)
{
perror("cancel thread");
return 1;
}
}
puts (" end of test");
return 0;
}
More information about the Libc-help
mailing list