mirror of
https://github.com/darlinghq/darling-libkqueue.git
synced 2024-11-23 11:49:50 +00:00
* Fix a race condition in kevent_wait() by holding the kqueue lock
for the duration of the kevent() function call. To avoid going to sleep with the lock, it is dropped temporarily before calling pselect() or similar system calls. Thanks to Eric Wong for reporting this bug. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/branches/stable@541 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
parent
d409012e4c
commit
993be36cda
@ -1,3 +1,11 @@
|
||||
2012-04-22 v1.0.7 r541
|
||||
------------------------------------------------------------------------
|
||||
|
||||
* Fix a race condition in kevent_wait() by holding the kqueue lock
|
||||
for the duration of the kevent() function call. To avoid going to
|
||||
sleep with the lock, it is dropped temporarily before calling
|
||||
pselect() or similar system calls.
|
||||
Thanks to Eric Wong for reporting this bug.
|
||||
|
||||
2012-04-19 v1.0.6 r539
|
||||
------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
program="libkqueue"
|
||||
version="1.0.6"
|
||||
version="1.0.7"
|
||||
abi_major="0"
|
||||
abi_minor="0"
|
||||
abi_version="$abi_major.$abi_minor"
|
||||
|
@ -248,21 +248,21 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges,
|
||||
return (-1);
|
||||
}
|
||||
|
||||
kqueue_lock(kq);
|
||||
|
||||
rv = kqueue_validate(kq);
|
||||
if (rv < 0) {
|
||||
return (-1);
|
||||
goto errout;
|
||||
} else if (rv == 0) {
|
||||
errno = EBADF;
|
||||
return (-1);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process each kevent on the changelist.
|
||||
*/
|
||||
if (nchanges) {
|
||||
kqueue_lock(kq);
|
||||
rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents);
|
||||
kqueue_unlock(kq);
|
||||
dbg_printf("changelist: rv=%d", rv);
|
||||
if (rv < 0)
|
||||
goto errout;
|
||||
@ -291,9 +291,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges,
|
||||
goto out; /* Timeout */
|
||||
|
||||
/* Copy the events to the caller */
|
||||
kqueue_lock(kq);
|
||||
nret = kevent_copyout(kq, n, eventlist, nevents);
|
||||
kqueue_unlock(kq);
|
||||
}
|
||||
|
||||
if (KQUEUE_DEBUG) {
|
||||
@ -309,6 +307,7 @@ errout:
|
||||
nret = -1;
|
||||
|
||||
out:
|
||||
kqueue_unlock(kq);
|
||||
kqueue_put(kq);
|
||||
return (nret);
|
||||
}
|
||||
|
@ -28,15 +28,12 @@ kevent_wait(struct kqueue *kq, const struct timespec *timeout)
|
||||
|
||||
dbg_puts("waiting for events");
|
||||
kq->kq_rfds = kq->kq_fds;
|
||||
kqueue_unlock(kq);
|
||||
n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
dbg_puts("signal caught");
|
||||
return (-1);
|
||||
}
|
||||
if (n < 0)
|
||||
dbg_perror("pselect(2)");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
kqueue_lock(kq);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
@ -90,23 +90,26 @@ kevent_wait(struct kqueue *kq, const struct timespec *timeout)
|
||||
|
||||
reset_errno();
|
||||
dbg_printf("waiting for events (timeout=%p)", timeout);
|
||||
kqueue_unlock(kq);
|
||||
rv = port_getn(kq->kq_port, pe, 1, &nget, (struct timespec *) timeout);
|
||||
dbg_printf("rv=%d errno=%d (%s) nget=%d",
|
||||
rv, errno, strerror(errno), nget);
|
||||
if (rv < 0) {
|
||||
if (errno == ETIME) {
|
||||
dbg_puts("no events within the given timeout");
|
||||
return (0);
|
||||
rv = 0;
|
||||
}
|
||||
if (errno == EINTR) {
|
||||
dbg_puts("signal caught");
|
||||
return (-1);
|
||||
rv = -1;
|
||||
}
|
||||
dbg_perror("port_get(2)");
|
||||
return (-1);
|
||||
} else {
|
||||
rv = nget;
|
||||
}
|
||||
|
||||
return (nget);
|
||||
kqueue_lock(kq);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user