Hung kernel from sysv semaphore semu_list corruption
Ed Maste
emaste at phaedrus.sandvine.ca
Thu Mar 8 14:42:49 UTC 2007
On Thu, Mar 08, 2007 at 10:55:22AM +0100, Divacky Roman wrote:
> this is wrong.. you cannot remove element from a *LIST when its iterated using *LIST_FOREACH.
> Use *LIST_FOREACH_SAFE instead...
We're not freeing the item in the loop so it would work unless
QUEUE_MACRO_DEBUG is turned on to intentionally trash the link
pointer on _REMOVE. You're right though it's not the correct approach.
There's an efficiency issue with the previous patch anyhow in that
SLIST_REMOVE walks the list again to find the element to remove.
How about the patch below instead:
Index: sysv_sem.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/sysv_sem.c,v
retrieving revision 1.85
diff -u -r1.85 sysv_sem.c
--- sysv_sem.c 22 Oct 2006 11:52:13 -0000 1.85
+++ sysv_sem.c 8 Mar 2007 14:22:43 -0000
@@ -1301,8 +1301,10 @@
*/
SEMUNDO_LOCK();
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) {
- if (suptr->un_proc == p)
+ if (suptr->un_proc == p) {
+ *supptr = SLIST_NEXT(suptr, un_next);
break;
+ }
}
SEMUNDO_UNLOCK();
@@ -1362,8 +1364,9 @@
* Deallocate the undo vector.
*/
DPRINTF(("removing vector\n"));
+ SEMUNDO_LOCK();
suptr->un_proc = NULL;
- *supptr = SLIST_NEXT(suptr, un_next);
+ SEMUNDO_UNLOCK();
}
More information about the freebsd-hackers
mailing list