diff options
author | tanimura <tanimura@FreeBSD.org> | 2001-05-15 10:19:57 +0000 |
---|---|---|
committer | tanimura <tanimura@FreeBSD.org> | 2001-05-15 10:19:57 +0000 |
commit | ac163f80253b962c608a2b093b66d7dbad78e43c (patch) | |
tree | ed154ff9bc31f68403ed7c49bcd0d3515131934d /sys/kern/sys_generic.c | |
parent | 6125cb47e354f8e71ec9dc19c0688d6c7b46a588 (diff) | |
download | FreeBSD-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/kern/sys_generic.c')
-rw-r--r-- | sys/kern/sys_generic.c | 36 |
1 files changed, 34 insertions, 2 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 ? |