Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Fri, 1 Mar 2002 11:39:07 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Fri, 1 Mar 2002 11:38:39 -0500 Received: from dell-paw-3.cambridge.redhat.com ([195.224.55.237]:5625 "HELO executor.cambridge.redhat.com") by vger.kernel.org with SMTP id ; Fri, 1 Mar 2002 11:38:13 -0500 To: Linus Torvalds Cc: David Howells , linux-kernel@vger.kernel.org Subject: Re: thread groups bug? In-Reply-To: Message from Dave McCracken of "Fri, 01 Mar 2002 10:24:30 CST." <36310000.1014999870@baldur> User-Agent: EMH/1.14.1 SEMI/1.14.3 (Ushinoya) FLIM/1.14.3 (=?ISO-8859-4?Q?Unebigory=F2mae?=) APEL/10.3 Emacs/21.1 (i386-redhat-linux-gnu) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: text/plain; charset=US-ASCII Date: Fri, 01 Mar 2002 16:38:11 +0000 Message-ID: <22890.1015000691@warthog.cambridge.redhat.com> From: David Howells Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Hi Linus, I've attached a patch to kill all subsidiary threads in a thread group when the main thread exits. I've made it against 2.5.6-pre1 since -pre2 fails to compile in the IDE code somewhere. I've tested it, and it appears to work. Note that it sends the subsidiary threads SIGKILL with SI_DETHREAD. Note also that subsidiary threads doing an execve() just leave the thread group (rather than forcing the master thread to do an execve() which would be more POSIX like). David diff -uNr linux-2.5.6-pre1/fs/exec.c linux-execve-256p1/fs/exec.c --- linux-2.5.6-pre1/fs/exec.c Wed Feb 27 08:26:55 2002 +++ linux-execve-256p1/fs/exec.c Fri Mar 1 15:37:36 2002 @@ -513,23 +513,49 @@ /* * An execve() will automatically "de-thread" the process. - * Note: we don't have to hold the tasklist_lock to test - * whether we migth need to do this. If we're not part of - * a thread group, there is no way we can become one - * dynamically. And if we are, we only need to protect the - * unlink - even if we race with the last other thread exit, - * at worst the list_del_init() might end up being a no-op. + * - if a master thread (PID==TGID) is doing this, then all subsidiary threads + * will be killed (otherwise there will end up being two independent thread + * groups with the same TGID). + * - if a subsidary thread is doing this, then it just leaves the thread group */ -static inline void de_thread(struct task_struct *tsk) +static void de_thread(struct task_struct *tsk) { - if (!list_empty(&tsk->thread_group)) { - write_lock_irq(&tasklist_lock); + struct task_struct *sub; + struct list_head *head, *ptr; + struct siginfo info; + int pause; + + write_lock_irq(&tasklist_lock); + + if (tsk->tgid != tsk->pid) { + /* subsidiary thread - just escapes the group */ + list_del_init(&tsk->thread_group); + tsk->tgid = tsk->pid; + pause = 0; + } + else { + /* master thread - kill all subsidiary threads */ + info.si_signo = SIGKILL; + info.si_errno = 0; + info.si_code = SI_DETHREAD; + info.si_pid = current->pid; + info.si_uid = current->uid; + + head = tsk->thread_group.next; list_del_init(&tsk->thread_group); - write_unlock_irq(&tasklist_lock); + + list_for_each(ptr,head) { + sub = list_entry(ptr,struct task_struct,thread_group); + send_sig_info(SIGKILL,&info,sub); + } + + pause = 1; } - /* Minor oddity: this might stay the same. */ - tsk->tgid = tsk->pid; + write_unlock_irq(&tasklist_lock); + + /* give the subsidiary threads a chance to clean themselves up */ + if (pause) yield(); } int flush_old_exec(struct linux_binprm * bprm) @@ -570,7 +596,8 @@ flush_thread(); - de_thread(current); + if (!list_empty(¤t->thread_group)) + de_thread(current); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || permission(bprm->file->f_dentry->d_inode,MAY_READ)) diff -uNr linux-2.5.6-pre1/include/asm-i386/siginfo.h linux-execve-256p1/include/asm-i386/siginfo.h --- linux-2.5.6-pre1/include/asm-i386/siginfo.h Wed Feb 27 08:27:01 2002 +++ linux-execve-256p1/include/asm-i386/siginfo.h Fri Mar 1 15:25:47 2002 @@ -108,6 +108,7 @@ #define SI_ASYNCIO -4 /* sent by AIO completion */ #define SI_SIGIO -5 /* sent by queued SIGIO */ #define SI_TKILL -6 /* sent by tkill system call */ +#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */ #define SI_FROMUSER(siptr) ((siptr)->si_code <= 0) #define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/