From: Oleg Nesterov setpgid(0, pgid) or setpgid(forked_child_pid, pgid) does not work unless the calling process is a thread_group_leader(). 'man setpgid' does not tell anything about that, so I consider this behaviour is a bug. Signed-off-by: Oleg Nesterov Cc: Oren Laadan Cc: Roland McGrath Signed-off-by: Andrew Morton --- kernel/sys.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff -puN kernel/sys.c~setpgid-should-work-for-sub-threads kernel/sys.c --- devel/kernel/sys.c~setpgid-should-work-for-sub-threads 2005-12-22 05:09:27.000000000 -0800 +++ devel-akpm/kernel/sys.c 2005-12-22 05:09:27.000000000 -0800 @@ -1085,10 +1085,11 @@ asmlinkage long sys_times(struct tms __u asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) { struct task_struct *p; + struct task_struct *group_leader = current->group_leader; int err = -EINVAL; if (!pid) - pid = current->pid; + pid = group_leader->pid; if (!pgid) pgid = pid; if (pgid < 0) @@ -1108,16 +1109,16 @@ asmlinkage long sys_setpgid(pid_t pid, p if (!thread_group_leader(p)) goto out; - if (p->parent == current || p->real_parent == current) { + if (p->parent == current || p->real_parent == group_leader) { err = -EPERM; - if (p->signal->session != current->signal->session) + if (p->signal->session != group_leader->signal->session) goto out; err = -EACCES; if (p->did_exec) goto out; } else { err = -ESRCH; - if (p != current) + if (p != group_leader) goto out; } @@ -1129,7 +1130,7 @@ asmlinkage long sys_setpgid(pid_t pid, p struct task_struct *p; do_each_task_pid(pgid, PIDTYPE_PGID, p) { - if (p->signal->session == current->signal->session) + if (p->signal->session == group_leader->signal->session) goto ok_pgid; } while_each_task_pid(pgid, PIDTYPE_PGID, p); goto out; _