summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2009-03-24 13:49:39 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2009-03-24 13:49:39 +0000
commit357c94f187ffcf56d0506c1f4373ce80a642ac5d (patch)
tree16b1fb9d86dfe438a6a7ef6781be26d42570d50f
parent54172b1e5b0d3690847aae62b3d74ae0316ea1a0 (diff)
Only copy out the revents field, not the whole pollfd structure. This
allows threaded programs to concurrently update the events field while a thread is blocked in poll(2). okay deraadt@ millert@
-rw-r--r--sys/kern/sys_generic.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index ac9d89dd38d..01eab771b5a 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_generic.c,v 1.59 2008/12/16 07:57:28 guenther Exp $ */
+/* $OpenBSD: sys_generic.c,v 1.60 2009/03/24 13:49:38 kurt Exp $ */
/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
/*
@@ -65,6 +65,7 @@
int selscan(struct proc *, fd_set *, fd_set *, int, int, register_t *);
int seltrue(dev_t, int, struct proc *);
void pollscan(struct proc *, struct pollfd *, u_int, register_t *);
+int pollout(struct pollfd *, struct pollfd *, u_int);
/*
* Read system call.
@@ -853,6 +854,25 @@ pollscan(struct proc *p, struct pollfd *pl, u_int nfd, register_t *retval)
}
/*
+ * Only copyout the revents field.
+ */
+int
+pollout(struct pollfd *pl, struct pollfd *upl, u_int nfds)
+{
+ int error = 0;
+ u_int i = 0;
+
+ while (!error && i++ < nfds) {
+ error = copyout(&pl->revents, &upl->revents,
+ sizeof(upl->revents));
+ pl++;
+ upl++;
+ }
+
+ return (error);
+}
+
+/*
* We are using the same mechanism as select only we encode/decode args
* differently.
*/
@@ -938,13 +958,13 @@ done:
*/
switch (error) {
case ERESTART:
- error = copyout(pl, SCARG(uap, fds), sz);
+ error = pollout(pl, SCARG(uap, fds), nfds);
if (error == 0)
error = EINTR;
break;
case EWOULDBLOCK:
case 0:
- error = copyout(pl, SCARG(uap, fds), sz);
+ error = pollout(pl, SCARG(uap, fds), nfds);
break;
}
bad: