Whoop. Ok, here's a new patch. I think this covers all the cases.
I've done some testing and it appears to do the right thing, please
look it over (the last patch had type-o's and didn't cover the correct
cases).
-Matt
Index: kern/kern_exit.c
===
RCS file: /home/ncvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.187
diff -u -r1.187 kern_exit.c
--- kern/kern_exit.c10 Dec 2002 02:33:44 - 1.187
+++ kern/kern_exit.c15 Dec 2002 01:45:15 -
@@ -287,7 +287,15 @@
* Need to do this early enough that we can still sleep.
* Can't free the entire vmspace as the kernel stack
* may be mapped within that space also.
+*
+* Processes sharing the same vmspace may exit in one order, and
+* get cleaned up by vmspace_exit() in a different order. The
+* last exiting process to reach this point releases as much of
+* the environment as it can, and the last process cleaned up
+* by vmspace_exit() (which decrements exitingcnt) cleans up the
+* remainder.
*/
+ ++vm-vm_exitingcnt;
if (--vm-vm_refcnt == 0) {
if (vm-vm_shm)
shmexit(p);
@@ -297,7 +305,6 @@
vm_page_unlock_queues();
(void) vm_map_remove(vm-vm_map, vm_map_min(vm-vm_map),
vm_map_max(vm-vm_map));
- vm-vm_freer = p;
}
sx_xlock(proctree_lock);
Index: vm/vm_map.c
===
RCS file: /home/ncvs/src/sys/vm/vm_map.c,v
retrieving revision 1.273
diff -u -r1.273 vm_map.c
--- vm/vm_map.c 1 Dec 2002 18:57:56 - 1.273
+++ vm/vm_map.c 15 Dec 2002 02:05:13 -
@@ -258,7 +258,7 @@
vm-vm_map.pmap = vmspace_pmap(vm); /* XXX */
vm-vm_refcnt = 1;
vm-vm_shm = NULL;
- vm-vm_freer = NULL;
+ vm-vm_exitingcnt = 0;
return (vm);
}
@@ -304,7 +304,7 @@
if (vm-vm_refcnt == 0)
panic(vmspace_free: attempt to free already freed vmspace);
- if (--vm-vm_refcnt == 0)
+ if (--vm-vm_refcnt == 0 vm-vm_exitingcnt == 0)
vmspace_dofree(vm);
}
@@ -314,11 +314,22 @@
struct vmspace *vm;
GIANT_REQUIRED;
- if (p == p-p_vmspace-vm_freer) {
- vm = p-p_vmspace;
- p-p_vmspace = NULL;
+ vm = p-p_vmspace;
+ p-p_vmspace = NULL;
+
+ /*
+* cleanup by parent process wait()ing on exiting child. vm_refcnt
+* may not be 0 (e.g. fork() and child exits without exec()ing).
+* exitingcnt may increment above 0 and drop back down to zero
+* several times while vm_refcnt is held non-zero. vm_refcnt
+* may also increment above 0 and drop back down to zero several
+* times while vm_exitingcnt is held non-zero.
+*
+* The last wait on the exiting child's vmspace will clean up
+* the remainder of the vmspace.
+*/
+ if (--vm-vm_exitingcnt == 0 vm-vm_refcnt == 0)
vmspace_dofree(vm);
- }
}
/*
Index: vm/vm_map.h
===
RCS file: /home/ncvs/src/sys/vm/vm_map.h,v
retrieving revision 1.92
diff -u -r1.92 vm_map.h
--- vm/vm_map.h 22 Sep 2002 04:33:43 - 1.92
+++ vm/vm_map.h 15 Dec 2002 01:47:49 -
@@ -218,8 +218,8 @@
caddr_t vm_taddr; /* (c) user virtual address of text */
caddr_t vm_daddr; /* (c) user virtual address of data */
caddr_t vm_maxsaddr;/* user VA at max stack growth */
-#definevm_endcopy vm_freer
- struct proc *vm_freer; /* vm freed on whose behalf */
+#definevm_endcopy vm_exitingcnt
+ int vm_exitingcnt; /* several processes zombied in exit1 */
};
#ifdef _KERNEL
To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message