kern/lwp: Check lwp_lock before remove lwp from process lwp tree
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Nov 2015 02:12:57 +0000 (10:12 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Nov 2015 02:15:10 +0000 (10:15 +0800)
This makes sure that lwp tree iteration with blocking operation
will not be broken.

While I'm here, add assertion lwp_lock == 0 in lwp_dispose()

sys/kern/kern_exit.c
sys/kern/kern_fork.c

index 2bdecfd..eb35dc4 100644 (file)
@@ -838,6 +838,7 @@ lwp_dispose(struct lwp *lp)
        struct thread *td = lp->lwp_thread;
 
        KKASSERT(lwkt_preempted_proc() != lp);
+       KKASSERT(lp->lwp_lock == 0);
        KKASSERT(td->td_refs == 0);
        KKASSERT((td->td_flags & (TDF_RUNNING |
                                  TDF_RUNQ |
@@ -986,6 +987,14 @@ loop:
                         * be zero.
                         */
                        while ((lp = RB_ROOT(&p->p_lwp_tree)) != NULL) {
+                               /*
+                                * Make sure no one is using this lwp, before
+                                * it is removed from the tree.  If we didn't
+                                * wait it here, lwp tree iteration with
+                                * blocking operation would be broken.
+                                */
+                               while (lp->lwp_lock > 0)
+                                       tsleep(lp, 0, "zomblwp", 1);
                                lwp_rb_tree_RB_REMOVE(&p->p_lwp_tree, lp);
                                reaplwp(lp);
                        }
index 2717f6c..f6ead9f 100644 (file)
@@ -221,6 +221,13 @@ sys_lwp_create(struct lwp_create_args *uap)
        return (0);
 
 fail:
+       /*
+        * Make sure no one is using this lwp, before it is removed from
+        * the tree.  If we didn't wait it here, lwp tree iteration with
+        * blocking operation would be broken.
+        */
+       while (lp->lwp_lock > 0)
+               tsleep(lp, 0, "lwpfail", 1);
        lwp_rb_tree_RB_REMOVE(&p->p_lwp_tree, lp);
        --p->p_nthreads;
        /* lwp_dispose expects an exited lwp, and a held proc */