From nobody@FreeBSD.org  Sun Dec 13 23:18:28 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 2A4AB106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 13 Dec 2009 23:18:28 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 18EC28FC19
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 13 Dec 2009 23:18:28 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nBDNIRZi080157
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 13 Dec 2009 23:18:27 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id nBDNIR8s080156;
	Sun, 13 Dec 2009 23:18:27 GMT
	(envelope-from nobody)
Message-Id: <200912132318.nBDNIR8s080156@www.freebsd.org>
Date: Sun, 13 Dec 2009 23:18:27 GMT
From: Stefan Schmidt <stefan.schmidt@stadtbuch.de>
To: freebsd-gnats-submit@FreeBSD.org
Subject: linux_exit_group kills group leader
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         141439
>Category:       kern
>Synopsis:       [linux] [patch] linux_exit_group kills group leader
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    netchild
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Dec 13 23:20:01 UTC 2009
>Closed-Date:    Wed Mar 02 10:11:29 UTC 2011
>Last-Modified:  Wed Mar 02 10:11:29 UTC 2011
>Originator:     Stefan Schmidt
>Release:        FreeBSD 8.0-STABLE as of 2009-12-13
>Organization:
>Environment:
FreeBSD shuttle.stadtbuch.de 8.0-STABLE FreeBSD 8.0-STABLE #0: Sun Dec 13 21:08:07 CET 2009     root@shuttle.stadtbuch.de:/usr/obj/usr/src/sys/SHUTTLE  amd64

>Description:
Using the 32-bit Linux version of Sun's Java Development Kit 1.6
(Update 17) on FreeBSD 8.0 (amd64), invocations of "javac" (or "java")
eventually end with the output of "Killed" and exit code 137.

This is particularly annoying when running e.g. JUnit-tests in a separate
process. The calling process always receives exit code 137 from its
sub-process and assumes that tests failed.
>How-To-Repeat:
shuttle# /usr/local/linux-sun-jdk1.6.0_17/bin/javac -version
javac 1.6.0_17
Killed
shuttle# echo $?
137
shuttle#
>Fix:
It seems that linux_exit_group (in linux_misc.c) unconditionally sends
SIGKILL to the leader of the thread group. This results in exit code 137
and the output of "Killed" as shown above.

I tried to modify linux_exit_group to not kill the group leader and to
set the exit code appropriately. While this modified linux_exit_group
works fine for me, I doubt it is correct (e.g. regarding locking).
I also had a closer look at NetBSD's version of linux_exit_group, but
could not get NetBSD's implementation approach to work (that is setting
p_xstat in linuxulator's process exit hook). Don't know (haven't tried)
whether it really works as expected in NetBSD anyway.

Please find my patch attached.

Patch attached with submission follows:

Index: sys/compat/linux/linux_emul.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_emul.c,v
retrieving revision 1.23.2.1
diff -u -w -d -r1.23.2.1 linux_emul.c
--- sys/compat/linux/linux_emul.c	3 Aug 2009 08:13:06 -0000	1.23.2.1
+++ sys/compat/linux/linux_emul.c	13 Dec 2009 21:22:40 -0000
@@ -96,6 +96,7 @@
 			s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO);
 			s->refs = 1;
 			s->group_pid = child;
+			s->xstat = 0;
 
 			LIST_INIT(&s->threads);
 			em->shared = s;
Index: sys/compat/linux/linux_emul.h
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_emul.h,v
retrieving revision 1.10.2.1
diff -u -w -d -r1.10.2.1 linux_emul.h
--- sys/compat/linux/linux_emul.h	3 Aug 2009 08:13:06 -0000	1.10.2.1
+++ sys/compat/linux/linux_emul.h	13 Dec 2009 21:22:18 -0000
@@ -36,6 +36,8 @@
 	pid_t	group_pid;
 
 	LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */
+	
+	int xstat;
 };
 
 /*
Index: sys/compat/linux/linux_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.240.2.2
diff -u -w -d -r1.240.2.2 linux_misc.c
--- sys/compat/linux/linux_misc.c	16 Sep 2009 13:24:37 -0000	1.240.2.2
+++ sys/compat/linux/linux_misc.c	13 Dec 2009 22:48:36 -0000
@@ -1708,10 +1708,19 @@
 
 		KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n"));
 
+		if (td_em->shared->refs == 1) {
+		    exit1(td, td_em->shared->xstat ? td_em->shared->xstat : W_EXITCODE(args->error_code, 0));
+		    return (0);
+		}
+		
 		EMUL_SHARED_RLOCK(&emul_shared_lock);
+
+		td_em->shared->xstat = W_EXITCODE(args->error_code, 0);
+
 		LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
-			if (em->pid == td_em->pid)
+			if ((em->pid == td_em->pid) || (em->pid == td_em->shared->group_pid))  {
 				continue;
+                        }
 
 			sp = pfind(em->pid);
 			psignal(sp, SIGKILL);
@@ -1721,8 +1730,18 @@
 #endif
 		}
 
+		if (td->td_proc->p_pid != td_em->shared->group_pid) {
+#ifdef DEBUG
+                    printf(LMSG("linux_sys_exit_group: kill PID %d\n"), td->td_proc->p_pid);
+#endif
+		    psignal(td->td_proc, SIGKILL);
+                }
+                
 		EMUL_SHARED_RUNLOCK(&emul_shared_lock);
+		
+		return (0);
 	}
+
 	/*
 	 * XXX: we should send a signal to the parent if
 	 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-emulation 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Dec 14 00:03:04 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141439 

From: Gleb Kurtsou <gleb.kurtsou@gmail.com>
To: Stefan Schmidt <stefan.schmidt@stadtbuch.de>
Cc: bug-followup@FreeBSD.org
Subject: Re: kern/141439: linux_exit_group kills group leader
Date: Mon, 22 Feb 2010 04:06:59 +0200

 On (13/12/2009 23:18), Stefan Schmidt wrote:
 [...]
 > Using the 32-bit Linux version of Sun's Java Development Kit 1.6
 > (Update 17) on FreeBSD 8.0 (amd64), invocations of "javac" (or "java")
 > eventually end with the output of "Killed" and exit code 137.
 > 
 > This is particularly annoying when running e.g. JUnit-tests in a
 > separate process. The calling process always receives exit code 137
 > from its sub-process and assumes that tests failed.
 
 Hi Stefan,
 
 I've experienced the same problem with sun jdk. I think approach of not
 killing group leader is incorrect, it should also be killed. Your patch
 works because linux_exit_group is called for the second time when only
 group leader is available. Such behavior is not expected, control should
 not return to userspace from linux_exit_group.
 
 I've submitted another PR, it contains fixes for 2 linux exec bugs.
 I've followed NetBSD and patched exit1() to allow process exit status to
 be changed by event handlers.
 
 Would appreciate if you could test the patch:
 http://www.freebsd.org/cgi/query-pr.cgi?pr=144194
 
 Thanks,
 Gleb

From: Stefan Schmidt <stefan.schmidt@stadtbuch.de>
To: Gleb Kurtsou <gleb.kurtsou@gmail.com>
Cc: bug-followup@FreeBSD.org
Subject: Re: kern/141439: linux_exit_group kills group leader
Date: Thu, 11 Mar 2010 00:35:20 +0100

 Hi Gleb,
 
 On 22.02.2010 03:06, Gleb Kurtsou wrote:
 > I've experienced the same problem with sun jdk. I think approach of not
 > killing group leader is incorrect, it should also be killed. Your patch
 > works because linux_exit_group is called for the second time when only
 > group leader is available. Such behavior is not expected, control should
 > not return to userspace from linux_exit_group.
 
 I agree - thanks for explaining.
 
 > I've submitted another PR, it contains fixes for 2 linux exec bugs.
 > I've followed NetBSD and patched exit1() to allow process exit status to
 > be changed by event handlers.
 >
 > Would appreciate if you could test the patch:
 > http://www.freebsd.org/cgi/query-pr.cgi?pr=144194
 
 Your patch works fine for me (RELENG_8).
 
 Kind regards
 
 Stefan
Responsible-Changed-From-To: freebsd-emulation->dchagin 
Responsible-Changed-By: dchagin 
Responsible-Changed-When: Mon Jul 5 21:44:38 UTC 2010 
Responsible-Changed-Why:  
Grab 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141439 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141439: commit references a PR
Date: Mon, 22 Nov 2010 09:07:08 +0000 (UTC)

 Author: netchild
 Date: Mon Nov 22 09:06:59 2010
 New Revision: 215664
 URL: http://svn.freebsd.org/changeset/base/215664
 
 Log:
   By using the 32-bit Linux version of Sun's Java Development Kit 1.6
   on FreeBSD (amd64), invocations of "javac" (or "java") eventually
   end with the output of "Killed" and exit code 137.
   
   This is caused by:
   1. After calling exec() in multithreaded linux program threads are not
      destroyed and continue running. They get killed after program being
      executed finishes.
   
   2. linux_exit_group doesn't return correct exit code when called not
      from group leader. Which happens regularly using sun jvm.
   
   The submitters fix this in a similar way to how NetBSD handles this.
   
   I took the PRs away from dchagin, who seems to be out of touch of
   this since a while (no response from him).
   
   The patches committed here are from [2], with some little modifications
   from me to the style.
   
   PR:		141439 [1], 144194 [2]
   Submitted by:	Stefan Schmidt <stefan.schmidt@stadtbuch.de>, gk
   Reviewed by:	rdivacky (in april 2010)
   MFC after:	5 days
 
 Modified:
   head/sys/compat/linux/linux_emul.c
   head/sys/compat/linux/linux_emul.h
   head/sys/compat/linux/linux_misc.c
   head/sys/kern/kern_exit.c
 
 Modified: head/sys/compat/linux/linux_emul.c
 ==============================================================================
 --- head/sys/compat/linux/linux_emul.c	Mon Nov 22 09:04:29 2010	(r215663)
 +++ head/sys/compat/linux/linux_emul.c	Mon Nov 22 09:06:59 2010	(r215664)
 @@ -155,7 +155,7 @@ void
  linux_proc_exit(void *arg __unused, struct proc *p)
  {
  	struct linux_emuldata *em;
 -	int error;
 +	int error, shared_flags, shared_xstat;
  	struct thread *td = FIRST_THREAD_IN_PROC(p);
  	int *child_clear_tid;
  	struct proc *q, *nq;
 @@ -187,6 +187,8 @@ linux_proc_exit(void *arg __unused, stru
  	}
  
  	EMUL_SHARED_WLOCK(&emul_shared_lock);
 +	shared_flags = em->shared->flags;
 +	shared_xstat = em->shared->xstat;
  	LIST_REMOVE(em, threads);
  
  	em->shared->refs--;
 @@ -196,6 +198,12 @@ linux_proc_exit(void *arg __unused, stru
  	} else	
  		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
  
 +	if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0) {
 +		PROC_LOCK(p);
 +		p->p_xstat = shared_xstat;
 +		PROC_UNLOCK(p);
 +	}
 +
  	if (child_clear_tid != NULL) {
  		struct linux_sys_futex_args cup;
  		int null = 0;
 @@ -257,6 +265,9 @@ linux_proc_exec(void *arg __unused, stru
  	if (__predict_false(imgp->sysent == &elf_linux_sysvec
  	    && p->p_sysent != &elf_linux_sysvec))
  		linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
 +	if (__predict_false(p->p_sysent == &elf_linux_sysvec))
 +		/* Kill threads regardless of imgp->sysent value */
 +		linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL);
  	if (__predict_false(imgp->sysent != &elf_linux_sysvec
  	    && p->p_sysent == &elf_linux_sysvec)) {
  		struct linux_emuldata *em;
 @@ -334,3 +345,29 @@ linux_set_tid_address(struct thread *td,
  	EMUL_UNLOCK(&emul_lock);
  	return 0;
  }
 +
 +void
 +linux_kill_threads(struct thread *td, int sig)
 +{
 +	struct linux_emuldata *em, *td_em, *tmp_em;
 +	struct proc *sp;
 +
 +	td_em = em_find(td->td_proc, EMUL_DONTLOCK);
 +
 +	KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n"));
 +
 +	EMUL_SHARED_RLOCK(&emul_shared_lock);
 +	LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
 +		if (em->pid == td_em->pid)
 +			continue;
 +
 +		sp = pfind(em->pid);
 +		if ((sp->p_flag & P_WEXIT) == 0)
 +			psignal(sp, sig);
 +		PROC_UNLOCK(sp);
 +#ifdef DEBUG
 +		printf(LMSG("linux_kill_threads: kill PID %d\n"), em->pid);
 +#endif
 +	}
 +	EMUL_SHARED_RUNLOCK(&emul_shared_lock);
 +}
 
 Modified: head/sys/compat/linux/linux_emul.h
 ==============================================================================
 --- head/sys/compat/linux/linux_emul.h	Mon Nov 22 09:04:29 2010	(r215663)
 +++ head/sys/compat/linux/linux_emul.h	Mon Nov 22 09:06:59 2010	(r215664)
 @@ -31,8 +31,12 @@
  #ifndef _LINUX_EMUL_H_
  #define	_LINUX_EMUL_H_
  
 +#define EMUL_SHARED_HASXSTAT	0x01
 +
  struct linux_emuldata_shared {
  	int	refs;
 +	int	flags;
 +	int	xstat;
  	pid_t	group_pid;
  
  	LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */
 @@ -76,6 +80,7 @@ int	linux_proc_init(struct thread *, pid
  void	linux_proc_exit(void *, struct proc *);
  void	linux_schedtail(void *, struct proc *);
  void	linux_proc_exec(void *, struct proc *, struct image_params *);
 +void	linux_kill_threads(struct thread *, int);
  
  extern struct sx	emul_shared_lock;
  extern struct mtx	emul_lock;
 
 Modified: head/sys/compat/linux/linux_misc.c
 ==============================================================================
 --- head/sys/compat/linux/linux_misc.c	Mon Nov 22 09:04:29 2010	(r215663)
 +++ head/sys/compat/linux/linux_misc.c	Mon Nov 22 09:06:59 2010	(r215664)
 @@ -1695,34 +1695,23 @@ linux_setdomainname(struct thread *td, s
  int
  linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
  {
 -	struct linux_emuldata *em, *td_em, *tmp_em;
 -	struct proc *sp;
 +	struct linux_emuldata *em;
  
  #ifdef DEBUG
  	if (ldebug(exit_group))
  		printf(ARGS(exit_group, "%i"), args->error_code);
  #endif
  
 -	if (linux_use26(td)) {
 -		td_em = em_find(td->td_proc, EMUL_DONTLOCK);
 -
 -		KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n"));
 -
 -		EMUL_SHARED_RLOCK(&emul_shared_lock);
 -		LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
 -			if (em->pid == td_em->pid)
 -				continue;
 -
 -			sp = pfind(em->pid);
 -			psignal(sp, SIGKILL);
 -			PROC_UNLOCK(sp);
 -#ifdef DEBUG
 -			printf(LMSG("linux_sys_exit_group: kill PID %d\n"), em->pid);
 -#endif
 -		}
 -
 -		EMUL_SHARED_RUNLOCK(&emul_shared_lock);
 +	em = em_find(td->td_proc, EMUL_DONTLOCK);
 +	if (em->shared->refs > 1) {
 +		EMUL_SHARED_WLOCK(&emul_shared_lock);
 +		em->shared->flags |= EMUL_SHARED_HASXSTAT;
 +		em->shared->xstat = W_EXITCODE(args->error_code, 0);
 +		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
 +		if (linux_use26(td))
 +			linux_kill_threads(td, SIGKILL);
  	}
 +
  	/*
  	 * XXX: we should send a signal to the parent if
  	 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)
 
 Modified: head/sys/kern/kern_exit.c
 ==============================================================================
 --- head/sys/kern/kern_exit.c	Mon Nov 22 09:04:29 2010	(r215663)
 +++ head/sys/kern/kern_exit.c	Mon Nov 22 09:06:59 2010	(r215664)
 @@ -200,6 +200,7 @@ exit1(struct thread *td, int rv)
  	while (p->p_lock > 0)
  		msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0);
  
 +	p->p_xstat = rv;	/* Let event handler change exit status */
  	PROC_UNLOCK(p);
  	/* Drain the limit callout while we don't have the proc locked */
  	callout_drain(&p->p_limco);
 @@ -242,6 +243,7 @@ exit1(struct thread *td, int rv)
  	 * P_PPWAIT is set; we will wakeup the parent below.
  	 */
  	PROC_LOCK(p);
 +	rv = p->p_xstat;	/* Event handler could change exit status */
  	stopprofclock(p);
  	p->p_flag &= ~(P_TRACED | P_PPWAIT);
  
 @@ -424,7 +426,6 @@ exit1(struct thread *td, int rv)
  
  	/* Save exit status. */
  	PROC_LOCK(p);
 -	p->p_xstat = rv;
  	p->p_xthread = td;
  
  	/* Tell the prison that we are gone. */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: netchild 
State-Changed-When: Mon Nov 22 09:10:37 UTC 2010 
State-Changed-Why:  
Patched with the patch from PR 144194. 


Responsible-Changed-From-To: dchagin->netchild 
Responsible-Changed-By: netchild 
Responsible-Changed-When: Mon Nov 22 09:10:37 UTC 2010 
Responsible-Changed-Why:  
Patched with the patch from PR 144194. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141439 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141439: commit references a PR
Date: Wed,  2 Mar 2011 09:53:33 +0000 (UTC)

 Author: netchild
 Date: Wed Mar  2 09:53:13 2011
 New Revision: 219173
 URL: http://svn.freebsd.org/changeset/base/219173
 
 Log:
   MFC r215664:
     By using the 32-bit Linux version of Sun's Java Development Kit 1.6
     on FreeBSD (amd64), invocations of "javac" (or "java") eventually
     end with the output of "Killed" and exit code 137.
   
     This is caused by:
     1. After calling exec() in multithreaded linux program threads are not
        destroyed and continue running. They get killed after program being
        executed finishes.
   
     2. linux_exit_group doesn't return correct exit code when called not
        from group leader. Which happens regularly using sun jvm.
   
     The submitters fix this in a similar way to how NetBSD handles this.
   
     I took the PRs away from dchagin, who seems to be out of touch of
     this since a while (no response from him).
   
     The patches committed here are from [2], with some little modifications
     from me to the style.
   
     PR:                141439 [1], 144194 [2]
     Submitted by:        Stefan Schmidt <stefan.schmidt@stadtbuch.de>, gk
     Reviewed by:        rdivacky (in april 2010)
   
   MFC r215675:
     Do not take the process lock. The assignment to u_short inside the
     properly aligned structure is atomic on all supported architectures, and
     the thread that should see side-effect of assignment is the same thread
     that does assignment.
   
     Use a more appropriate conditional to detect the linux ABI.
   
     Suggested by:        kib
 
 Modified:
   stable/8/sys/compat/linux/linux_emul.c
   stable/8/sys/compat/linux/linux_emul.h
   stable/8/sys/compat/linux/linux_misc.c
   stable/8/sys/kern/kern_exit.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/compat/linux/linux_emul.c
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_emul.c	Wed Mar  2 06:24:46 2011	(r219172)
 +++ stable/8/sys/compat/linux/linux_emul.c	Wed Mar  2 09:53:13 2011	(r219173)
 @@ -155,7 +155,7 @@ void
  linux_proc_exit(void *arg __unused, struct proc *p)
  {
  	struct linux_emuldata *em;
 -	int error;
 +	int error, shared_flags, shared_xstat;
  	struct thread *td = FIRST_THREAD_IN_PROC(p);
  	int *child_clear_tid;
  	struct proc *q, *nq;
 @@ -187,6 +187,8 @@ linux_proc_exit(void *arg __unused, stru
  	}
  
  	EMUL_SHARED_WLOCK(&emul_shared_lock);
 +	shared_flags = em->shared->flags;
 +	shared_xstat = em->shared->xstat;
  	LIST_REMOVE(em, threads);
  
  	em->shared->refs--;
 @@ -196,6 +198,9 @@ linux_proc_exit(void *arg __unused, stru
  	} else	
  		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
  
 +	if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0)
 +		p->p_xstat = shared_xstat;
 +
  	if (child_clear_tid != NULL) {
  		struct linux_sys_futex_args cup;
  		int null = 0;
 @@ -257,6 +262,10 @@ linux_proc_exec(void *arg __unused, stru
  	if (__predict_false(imgp->sysent == &elf_linux_sysvec
  	    && p->p_sysent != &elf_linux_sysvec))
  		linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
 +	if (__predict_false((p->p_sysent->sv_flags & SV_ABI_MASK) ==
 +	    SV_ABI_LINUX))
 +		/* Kill threads regardless of imgp->sysent value */
 +		linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL);
  	if (__predict_false(imgp->sysent != &elf_linux_sysvec
  	    && p->p_sysent == &elf_linux_sysvec)) {
  		struct linux_emuldata *em;
 @@ -334,3 +343,29 @@ linux_set_tid_address(struct thread *td,
  	EMUL_UNLOCK(&emul_lock);
  	return 0;
  }
 +
 +void
 +linux_kill_threads(struct thread *td, int sig)
 +{
 +	struct linux_emuldata *em, *td_em, *tmp_em;
 +	struct proc *sp;
 +
 +	td_em = em_find(td->td_proc, EMUL_DONTLOCK);
 +
 +	KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n"));
 +
 +	EMUL_SHARED_RLOCK(&emul_shared_lock);
 +	LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
 +		if (em->pid == td_em->pid)
 +			continue;
 +
 +		sp = pfind(em->pid);
 +		if ((sp->p_flag & P_WEXIT) == 0)
 +			psignal(sp, sig);
 +		PROC_UNLOCK(sp);
 +#ifdef DEBUG
 +		printf(LMSG("linux_kill_threads: kill PID %d\n"), em->pid);
 +#endif
 +	}
 +	EMUL_SHARED_RUNLOCK(&emul_shared_lock);
 +}
 
 Modified: stable/8/sys/compat/linux/linux_emul.h
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_emul.h	Wed Mar  2 06:24:46 2011	(r219172)
 +++ stable/8/sys/compat/linux/linux_emul.h	Wed Mar  2 09:53:13 2011	(r219173)
 @@ -31,8 +31,12 @@
  #ifndef _LINUX_EMUL_H_
  #define	_LINUX_EMUL_H_
  
 +#define EMUL_SHARED_HASXSTAT	0x01
 +
  struct linux_emuldata_shared {
  	int	refs;
 +	int	flags;
 +	int	xstat;
  	pid_t	group_pid;
  
  	LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */
 @@ -76,6 +80,7 @@ int	linux_proc_init(struct thread *, pid
  void	linux_proc_exit(void *, struct proc *);
  void	linux_schedtail(void *, struct proc *);
  void	linux_proc_exec(void *, struct proc *, struct image_params *);
 +void	linux_kill_threads(struct thread *, int);
  
  extern struct sx	emul_shared_lock;
  extern struct mtx	emul_lock;
 
 Modified: stable/8/sys/compat/linux/linux_misc.c
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_misc.c	Wed Mar  2 06:24:46 2011	(r219172)
 +++ stable/8/sys/compat/linux/linux_misc.c	Wed Mar  2 09:53:13 2011	(r219173)
 @@ -1655,34 +1655,23 @@ linux_setdomainname(struct thread *td, s
  int
  linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
  {
 -	struct linux_emuldata *em, *td_em, *tmp_em;
 -	struct proc *sp;
 +	struct linux_emuldata *em;
  
  #ifdef DEBUG
  	if (ldebug(exit_group))
  		printf(ARGS(exit_group, "%i"), args->error_code);
  #endif
  
 -	if (linux_use26(td)) {
 -		td_em = em_find(td->td_proc, EMUL_DONTLOCK);
 -
 -		KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n"));
 -
 -		EMUL_SHARED_RLOCK(&emul_shared_lock);
 -		LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
 -			if (em->pid == td_em->pid)
 -				continue;
 -
 -			sp = pfind(em->pid);
 -			psignal(sp, SIGKILL);
 -			PROC_UNLOCK(sp);
 -#ifdef DEBUG
 -			printf(LMSG("linux_sys_exit_group: kill PID %d\n"), em->pid);
 -#endif
 -		}
 -
 -		EMUL_SHARED_RUNLOCK(&emul_shared_lock);
 +	em = em_find(td->td_proc, EMUL_DONTLOCK);
 +	if (em->shared->refs > 1) {
 +		EMUL_SHARED_WLOCK(&emul_shared_lock);
 +		em->shared->flags |= EMUL_SHARED_HASXSTAT;
 +		em->shared->xstat = W_EXITCODE(args->error_code, 0);
 +		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
 +		if (linux_use26(td))
 +			linux_kill_threads(td, SIGKILL);
  	}
 +
  	/*
  	 * XXX: we should send a signal to the parent if
  	 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)
 
 Modified: stable/8/sys/kern/kern_exit.c
 ==============================================================================
 --- stable/8/sys/kern/kern_exit.c	Wed Mar  2 06:24:46 2011	(r219172)
 +++ stable/8/sys/kern/kern_exit.c	Wed Mar  2 09:53:13 2011	(r219173)
 @@ -200,6 +200,7 @@ exit1(struct thread *td, int rv)
  	while (p->p_lock > 0)
  		msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0);
  
 +	p->p_xstat = rv;	/* Let event handler change exit status */
  	PROC_UNLOCK(p);
  	/* Drain the limit callout while we don't have the proc locked */
  	callout_drain(&p->p_limco);
 @@ -242,6 +243,7 @@ exit1(struct thread *td, int rv)
  	 * P_PPWAIT is set; we will wakeup the parent below.
  	 */
  	PROC_LOCK(p);
 +	rv = p->p_xstat;	/* Event handler could change exit status */
  	stopprofclock(p);
  	p->p_flag &= ~(P_TRACED | P_PPWAIT);
  
 @@ -421,7 +423,6 @@ exit1(struct thread *td, int rv)
  
  	/* Save exit status. */
  	PROC_LOCK(p);
 -	p->p_xstat = rv;
  	p->p_xthread = td;
  
  	/* Tell the prison that we are gone. */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: netchild 
State-Changed-When: Wed Mar 2 10:10:46 UTC 2011 
State-Changed-Why:  
The fix is now in 8-stable. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141439 
>Unformatted:
