summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-10-27 10:55:34 +0000
committerkib <kib@FreeBSD.org>2009-10-27 10:55:34 +0000
commit08e50139380f182b37e3e8f5bc7c1319119a4abd (patch)
tree707b4bb2816586b23064a94f87f2fbfdd1dc7380 /lib/libthr
parentce081b037e7a762f0dd090a207cafc5121f39f51 (diff)
downloadFreeBSD-src-08e50139380f182b37e3e8f5bc7c1319119a4abd.zip
FreeBSD-src-08e50139380f182b37e3e8f5bc7c1319119a4abd.tar.gz
Current pselect(3) is implemented in usermode and thus vulnerable to
well-known race condition, which elimination was the reason for the function appearance in first place. If sigmask supplied as argument to pselect() enables a signal, the signal might be delivered before thread called select(2), causing lost wakeup. Reimplement pselect() in kernel, making change of sigmask and sleep atomic. Since signal shall be delivered to the usermode, but sigmask restored, set TDP_OLDMASK and save old mask in td_oldsigmask. The TDP_OLDMASK should be cleared by ast() in case signal was not gelivered during syscall execution. Reviewed by: davidxu Tested by: pho MFC after: 1 month
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_syscalls.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index d05d68b..92670a9 100644
--- a/lib/libthr/thread/thr_syscalls.c
+++ b/lib/libthr/thread/thr_syscalls.c
@@ -104,6 +104,8 @@ extern int __sys_accept(int, struct sockaddr *, socklen_t *);
extern int __sys_connect(int, const struct sockaddr *, socklen_t);
extern int __sys_fsync(int);
extern int __sys_msync(void *, size_t, int);
+extern int __sys_pselect(int, fd_set *, fd_set *, fd_set *,
+ const struct timespec *, const sigset_t *);
extern int __sys_poll(struct pollfd *, unsigned, int);
extern ssize_t __sys_recv(int, void *, size_t, int);
extern ssize_t __sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
@@ -394,7 +396,7 @@ ___pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
int ret;
_thr_cancel_enter(curthread);
- ret = __pselect(count, rfds, wfds, efds, timo, mask);
+ ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
_thr_cancel_leave(curthread);
return (ret);
OpenPOWER on IntegriCloud