From 4cd4553bb53da6eff2e16385db01ba95bd7d7266 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 19 Mar 2008 07:13:24 +0000 Subject: [PATCH] - Fix the last of the threading bugs that were introduced as far back as 1.38 in 2001. Break out of the FOREACH_THREAD_IN_PROC loop when we've discovered a new proc in the chain. - Increment i and check for maxlockdepth once per matching process not once per thread. This didn't properly terminate the loop before. - Fix a bug which has existed potentially since rev 1.1. waitblock->lf_next can be NULL when a thread has been woken-up but not yet scheduled. Check for this condition rather than blindly dereferencing. Found by: libMicro --- sys/kern/kern_lockf.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_lockf.c b/sys/kern/kern_lockf.c index 6cce5aa880cb..95ac99d9acd0 100644 --- a/sys/kern/kern_lockf.c +++ b/sys/kern/kern_lockf.c @@ -286,28 +286,34 @@ restart: PROC_LOCK(wproc); FOREACH_THREAD_IN_PROC(wproc, td) { thread_lock(td); - while (td->td_wchan && - (td->td_wmesg == lockstr) && - (i++ < maxlockdepth)) { + for (;;) { + if (!TD_ON_SLEEPQ(td) || + td->td_wmesg != lockstr) + break; waitblock = (struct lockf *)td->td_wchan; /* Get the owner of the blocking lock */ + if (waitblock->lf_next == NULL) + break; waitblock = waitblock->lf_next; if ((waitblock->lf_flags & F_POSIX) == 0) break; - nproc = (struct proc *)waitblock->lf_id; - if (nproc == (struct proc *)lock->lf_id) { + if (waitblock->lf_id == lock->lf_id) { thread_unlock(td); PROC_UNLOCK(wproc); lock->lf_next = *clean; *clean = lock; return (EDEADLK); } + nproc = (struct proc *)waitblock->lf_id; + break; } thread_unlock(td); + if (nproc) + break; } PROC_UNLOCK(wproc); wproc = nproc; - if (wproc) + if (++i < maxlockdepth && wproc) goto restart; } /*