summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-03-11 22:00:03 +0000
committerrwatson <rwatson@FreeBSD.org>2009-03-11 22:00:03 +0000
commit843cb67ec07766f86673a964bf00a49b9871ba9b (patch)
tree05f579393beea8044802da725fd50ad0734f1334
parent2548f05c6c8be3fe53f4191e634699bb4fa4c56b (diff)
downloadFreeBSD-src-843cb67ec07766f86673a964bf00a49b9871ba9b.zip
FreeBSD-src-843cb67ec07766f86673a964bf00a49b9871ba9b.tar.gz
When writing out updated pollfd records when returning from
poll(), only copy out the revents field, not the whole pollfd structure. Otherwise, if the events field is updated concurrently by another thread, that update may be lost. This issue apparently causes problems for the JDK on FreeBSD, which expects the Linux behavior of not updating all fields (somewhat oddly, Solaris does not implement the required behavior, but presumably our adaptation of the JDK is based on the Linux port?). MFC after: 2 weeks PR: kern/130924 Submitted by: Kurt Miller <kurt @ intricatesoftware.com> Discussed with: kib
-rw-r--r--sys/kern/sys_generic.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index ad7c32e..d4af4cb 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -76,6 +76,7 @@ static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
MALLOC_DEFINE(M_IOV, "iov", "large iov's");
+static int pollout(struct pollfd *, struct pollfd *, u_int);
static int pollscan(struct thread *, struct pollfd *, u_int);
static int pollrescan(struct thread *);
static int selscan(struct thread *, fd_mask **, fd_mask **, int);
@@ -1128,7 +1129,7 @@ done:
if (error == EWOULDBLOCK)
error = 0;
if (error == 0) {
- error = copyout(bits, uap->fds, ni);
+ error = pollout(bits, uap->fds, nfds);
if (error)
goto out;
}
@@ -1183,6 +1184,26 @@ pollrescan(struct thread *td)
static int
+pollout(fds, ufds, nfd)
+ struct pollfd *fds;
+ struct pollfd *ufds;
+ u_int nfd;
+{
+ int error = 0;
+ u_int i = 0;
+
+ for (i = 0; i < nfd; i++) {
+ error = copyout(&fds->revents, &ufds->revents,
+ sizeof(ufds->revents));
+ if (error)
+ return (error);
+ fds++;
+ ufds++;
+ }
+ return (0);
+}
+
+static int
pollscan(td, fds, nfd)
struct thread *td;
struct pollfd *fds;
OpenPOWER on IntegriCloud