Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Feb 1999 12:17:40 -0500 (EST)
From:      Brian Feldman <green@unixhelp.org>
To:        current@freebsd.org
Subject:   More kernel threading ;)
Message-ID:  <Pine.BSF.4.05.9902201202140.23323-100000@janus.syracuse.net>

next in thread | raw e-mail | index | archive | help
  This time I've got a problem with LinuxThreads (again), but really any kernel
threads. Anyway, for those who say to put your patches where your mouth is,
this is a pretty annoying problem which I have solved, and I've provided a
fix. So here goes:

  With RFMEM, a shared address space is created and p->p_vmspace->vm_refcnt is
incremented. With shared memory, p->p_vmspace->vm_shm is allocated and used.
Now when processes exit (in the code before this patch), if vm_refcnt is not
1, shared memory is not taken care of at all. Instead, I changed it so that
shared memory's shm_nattch is decreased, and if < 1, freed. This solves the
problem of:

p1: fork1(RFMEM)
p[12]: shm create/attach
kill -9 p2 (no chance for the process to catch the signal and delete the
shared memory correctly)
exit1(p2)-> vm_refcnt--, shm not deleted/unreferenced
p1: no child! *SPLAT*
exit1(p1)-> vm_refcnt-- == 1, vm deleted and shm tried to be deleted:
shmexit-> shm all tried to be freed, but refcnt > 0, so it's not really deleted
and refcnt is dec'd once

You end up with (ipcs -a) a shared memory segment with a refcnt of 1, being
SET deleted but still there, and undeleteable because its' refcnt is 1 (refcnt
being shm_nattch...).

And the patch follows :)

--- src/sys/kern/sysv_shm.c.old	Sat Feb 20 11:36:15 1999
+++ src/sys/kern/sysv_shm.c	Sat Feb 20 11:46:19 1999
@@ -596,10 +596,13 @@
 
 	shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
 	for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
-		if (shmmap_s->shmid != -1)
+		if (shmmap_s->shmid != -1 &&
+			--shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch < 1)
 			shm_delete_mapping(p, shmmap_s);
-	free((caddr_t)p->p_vmspace->vm_shm, M_SHM);
-	p->p_vmspace->vm_shm = NULL;
+	if (p->p_vmspace->vm_refcnt == 1) {
+		free((caddr_t)p->p_vmspace->vm_shm, M_SHM);
+		p->p_vmspace->vm_shm = NULL;
+	}
 }
 
 void
--- src/sys/kern/kern_exit.c.old	Sat Feb 20 11:36:02 1999
+++ src/sys/kern/kern_exit.c	Sat Feb 20 11:46:22 1999
@@ -206,6 +206,10 @@
 
 	/* The next two chunks should probably be moved to vmspace_exit. */
 	vm = p->p_vmspace;
+
+	if (vm->vm_shm)
+		shmexit(p);
+
 	/*
 	 * Release user portion of address space.
 	 * This releases references to vnodes,
@@ -215,8 +219,6 @@
 	 * may be mapped within that space also.
 	 */
 	if (vm->vm_refcnt == 1) {
-		if (vm->vm_shm)
-			shmexit(p);
 		pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS,
 		    VM_MAXUSER_ADDRESS);
 		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,


 Brian Feldman					  _ __  ___ ___ ___  
 green@unixhelp.org			      _ __ ___ | _ ) __|   \ 
	     http://www.freebsd.org/	 _ __ ___ ____ | _ \__ \ |) |
 FreeBSD: The Power to Serve!	   _ __ ___ ____ _____ |___/___/___/ 



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9902201202140.23323-100000>