summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2001-05-15 10:19:57 +0000
committertanimura <tanimura@FreeBSD.org>2001-05-15 10:19:57 +0000
commitac163f80253b962c608a2b093b66d7dbad78e43c (patch)
treeed154ff9bc31f68403ed7c49bcd0d3515131934d /sys
parent6125cb47e354f8e71ec9dc19c0688d6c7b46a588 (diff)
downloadFreeBSD-src-ac163f80253b962c608a2b093b66d7dbad78e43c.zip
FreeBSD-src-ac163f80253b962c608a2b093b66d7dbad78e43c.tar.gz
Back out scanning file descriptors with holding a process lock.
selrecord() requires allproc sx in pfind(), resulting in lock order reversal between allproc and a process lock.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/sys_generic.c36
-rw-r--r--sys/netncp/ncp_sock.c18
-rw-r--r--sys/netsmb/smb_trantcp.c18
3 files changed, 66 insertions, 6 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index c43c688..e4db30d 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -768,13 +768,29 @@ select(p, uap)
retry:
ncoll = nselcoll;
p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
error = selscan(p, ibits, obits, uap->nd);
+ PROC_LOCK(p);
if (error || p->p_retval[0])
goto done;
if (atv.tv_sec || atv.tv_usec) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=))
+ if (timevalcmp(&rtv, &atv, >=)) {
+ /*
+ * An event of our interest may occur during locking a process.
+ * In order to avoid missing the event that occured during locking
+ * the process, test P_SELECT and rescan file descriptors if
+ * necessary.
+ */
+ if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
+ ncoll = nselcoll;
+ p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
+ error = selscan(p, ibits, obits, uap->nd);
+ PROC_LOCK(p);
+ }
goto done;
+ }
ttv = atv;
timevalsub(&ttv, &rtv);
timo = ttv.tv_sec > 24 * 60 * 60 ?
@@ -958,13 +974,29 @@ poll(p, uap)
retry:
ncoll = nselcoll;
p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
error = pollscan(p, (struct pollfd *)bits, nfds);
+ PROC_LOCK(p);
if (error || p->p_retval[0])
goto done;
if (atv.tv_sec || atv.tv_usec) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=))
+ if (timevalcmp(&rtv, &atv, >=)) {
+ /*
+ * An event of our interest may occur during locking a process.
+ * In order to avoid missing the event that occured during locking
+ * the process, test P_SELECT and rescan file descriptors if
+ * necessary.
+ */
+ if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
+ ncoll = nselcoll;
+ p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
+ error = pollscan(p, (struct pollfd *)bits, nfds);
+ PROC_LOCK(p);
+ }
goto done;
+ }
ttv = atv;
timevalsub(&ttv, &rtv);
timo = ttv.tv_sec > 24 * 60 * 60 ?
diff --git a/sys/netncp/ncp_sock.c b/sys/netncp/ncp_sock.c
index 063d007..2033441 100644
--- a/sys/netncp/ncp_sock.c
+++ b/sys/netncp/ncp_sock.c
@@ -202,17 +202,31 @@ ncp_sock_rselect(struct socket *so,struct proc *p, struct timeval *tv, int event
}
timo = 0;
PROC_LOCK(p);
-retry:
p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
error = ncp_poll(so, events);
+ PROC_LOCK(p);
if (error) {
error = 0;
goto done;
}
if (tv) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=))
+ if (timevalcmp(&rtv, &atv, >=)) {
+ /*
+ * An event of our interest may occur during locking a process.
+ * In order to avoid missing the event that occured during locking
+ * the process, test P_SELECT and rescan file descriptors if
+ * necessary.
+ */
+ if ((p->p_flag & P_SELECT) == 0) {
+ p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
+ error = ncp_poll(so, events);
+ PROC_LOCK(p);
+ }
goto done;
+ }
ttv=atv;
timevalsub(&ttv, &rtv);
timo = tvtohz(&ttv);
diff --git a/sys/netsmb/smb_trantcp.c b/sys/netsmb/smb_trantcp.c
index fea2469..3d6b082 100644
--- a/sys/netsmb/smb_trantcp.c
+++ b/sys/netsmb/smb_trantcp.c
@@ -114,17 +114,31 @@ nbssn_rselect(struct nbpcb *nbp, struct timeval *tv, int events, struct proc *p)
}
timo = 0;
PROC_LOCK(p);
-retry:
p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
error = nb_poll(nbp, events, p);
+ PROC_LOCK(p);
if (error) {
error = 0;
goto done;
}
if (tv) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=))
+ if (timevalcmp(&rtv, &atv, >=)) {
+ /*
+ * An event of our interest may occur during locking a process.
+ * In order to avoid missing the event that occured during locking
+ * the process, test P_SELECT and rescan file descriptors if
+ * necessary.
+ */
+ if ((p->p_flag & P_SELECT) == 0) {
+ p->p_flag |= P_SELECT;
+ PROC_UNLOCK(p);
+ error = nb_poll(nbp, events, p);
+ PROC_LOCK(p);
+ }
goto done;
+ }
ttv = atv;
timevalsub(&ttv, &rtv);
timo = tvtohz(&ttv);
OpenPOWER on IntegriCloud