poll() system call overwrites the complete pollfd struct instead of just revents
poll() system call overwrites the complete pollfd struct instead of just revents
- Subject: poll() system call overwrites the complete pollfd struct instead of just revents
- From: Kurt Miller <email@hidden>
- Date: Mon, 26 Jan 2009 10:47:38 -0500
For multi-threaded programs like Sun's JDK, an unexpected problem can
happen due to the kernel writing over the complete pollfd struct upon
return from the poll system call. Say thread A is blocked in the poll
system call and thread B modifies the events field. Then thread B wakes
up thread A, which returns from the system call and unexpectedly
overwrites the events field, erasing the changes made by thread B. In
Sun's JDK, thread A loops back to poll expecting the changes thread B
made to the events field to persist.
Both Solaris and Linux don't modify the events field. POSIX doesn't
specify either way, but it seems to be a reasonable assumption that the
kernel only write to the revents field.
Here is a test program that demonstrates the problem.
#include <err.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
struct pollfd fds[2];
int pipefds[2];
static void *
thread(void *arg) {
sleep(1);
fds[0].events = POLLIN | POLLOUT;
write(pipefds[1], "", 1);
return NULL;
}
int
main(int argc, char *argv[]) {
pthread_t tid;
if (pipe(pipefds) != 0)
err(1, "pipe failed");
fds[0].fd = pipefds[0];
fds[0].events = POLLIN;
fds[1].fd = pipefds[1];
fds[1].events = POLLIN;
if (pthread_create(&tid, NULL, thread, NULL) != 0)
err(1, "pthread_create failed");
poll(fds, 2, -1);
if (fds[0].events != (POLLIN | POLLOUT)) {
printf("events overwritten by kernel!\n");
return 1;
}
return 0;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden