Messages in this thread Patch in this message | | | From | Tim Hockin <> | Subject | Final(?) Patch : CLONE_PPID, CLONE_WAIT, CLONE_SUSPENDED | Date | Sat, 31 Jul 1999 15:41:48 -0500 (CDT) |
| |
Here is the final patch with various fixes and suggested checks included. Does anyone see anything else it is missing?
diff -ru clean-linux-2.2.10/fs/exec.c linux-2.2.10/fs/exec.c --- clean-linux-2.2.10/fs/exec.c Sun Jun 13 10:50:04 1999 +++ linux-2.2.10/fs/exec.c Thu Jul 22 03:17:00 1999 @@ -846,9 +846,12 @@ if (retval >= 0) retval = search_binary_handler(&bprm,regs); - if (retval >= 0) + if (retval >= 0) { + /* clear any thread-special bits - JIC */ + current->flags &= ~(PF_PPIDOK | PF_CLWAIT); /* execve success */ return retval; + } /* Something went wrong, return the inode and free the argument pages*/ if (bprm.dentry) diff -ru clean-linux-2.2.10/include/linux/sched.h linux-2.2.10/include/linux/sched.h --- clean-linux-2.2.10/include/linux/sched.h Tue May 11 10:35:45 1999 +++ linux-2.2.10/include/linux/sched.h Thu Jul 22 02:51:17 1999 @@ -34,6 +34,10 @@ #define CLONE_PID 0x00001000 /* set if pid shared */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ +#define CLONE_PPIDOK 0x00008000 /* set if the child should be able to create siblings */ +#define CLONE_PPID 0x00010000 /* set if we want to create a sibling, not a child */ +#define CLONE_WAIT 0x00020000 /* set if child is allowed to wait() for siblings */ +#define CLONE_SUSPENDED 0x00040000 /* create a process in the stopped state */ /* * These are the constant used to fake the fixed-point load-average @@ -332,6 +336,8 @@ #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ #define PF_DTRACE 0x00200000 /* delayed trace (used on m68k, i386) */ +#define PF_PPIDOK 0x00400000 /* task is allowed to use CLONE_PPID */ +#define PF_CLWAIT 0x00800000 /* allowed to wait for siblings */ /* * Limit the stack by to some sane default: root can always diff -ru clean-linux-2.2.10/kernel/exit.c linux-2.2.10/kernel/exit.c --- clean-linux-2.2.10/kernel/exit.c Fri Apr 30 08:13:37 1999 +++ linux-2.2.10/kernel/exit.c Thu Jul 29 10:09:11 1999 @@ -145,6 +145,7 @@ read_lock(&tasklist_lock); for_each_task(p) { if (p->p_opptr == father) { + p->flags &= ~(PF_PPIDOK | PF_CLWAIT); p->exit_signal = SIGCHLD; p->p_opptr = child_reaper; /* init */ if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0); @@ -403,76 +404,90 @@ do_exit((error_code&0xff)<<8); } +/* to get around the ugly macro below */ +static inline void wait4_audit_ptree() +{ +#ifdef DEBUG_PROC_TREE + audit_ptree(); +#endif +} + +#define SYS_WAIT4_SEARCH(start_task) \ + for (p = (start_task); p ; p = p->p_osptr) { \ + if (pid>0) { \ + if (p->pid != pid || current->pid == pid) \ + continue; \ + } else if (!pid) { \ + if (p->pgrp != current->pgrp) \ + continue; \ + } else if (pid != -1) { \ + if (p->pgrp != -pid) \ + continue; \ + } \ + /* wait for cloned processes iff the __WCLONE flag is set */ \ + if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) \ + continue; \ + flag = 1; \ + switch (p->state) { \ + case TASK_STOPPED: \ + if (!p->exit_code) \ + continue; \ + if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED)) \ + continue; \ + read_unlock(&tasklist_lock); \ + retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; \ + if (!retval && stat_addr) \ + retval = put_user((p->exit_code << 8) | 0x7f, stat_addr); \ + if (!retval) { \ + p->exit_code = 0; \ + retval = p->pid; \ + } \ + goto end_wait4; \ + case TASK_ZOMBIE: \ + current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; \ + current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; \ + read_unlock(&tasklist_lock); \ + retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; \ + if (!retval && stat_addr) \ + retval = put_user(p->exit_code, stat_addr); \ + if (retval) \ + goto end_wait4; \ + retval = p->pid; \ + if (p->p_opptr != p->p_pptr) { \ + write_lock_irq(&tasklist_lock); \ + REMOVE_LINKS(p); \ + p->p_pptr = p->p_opptr; \ + SET_LINKS(p); \ + write_unlock_irq(&tasklist_lock); \ + notify_parent(p, SIGCHLD); \ + } else \ + release(p); \ + wait4_audit_ptree(); \ + goto end_wait4; \ + default: \ + continue; \ + } \ + } \ + asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru) { int flag, retval; struct wait_queue wait = { current, NULL }; + struct wait_queue wait_sib = { current, NULL }; struct task_struct *p; if (options & ~(WNOHANG|WUNTRACED|__WCLONE)) return -EINVAL; add_wait_queue(¤t->wait_chldexit,&wait); + if (current->flags & PF_CLWAIT) + add_wait_queue(¤t->p_pptr->wait_chldexit,&wait_sib); repeat: flag = 0; read_lock(&tasklist_lock); - for (p = current->p_cptr ; p ; p = p->p_osptr) { - if (pid>0) { - if (p->pid != pid) - continue; - } else if (!pid) { - if (p->pgrp != current->pgrp) - continue; - } else if (pid != -1) { - if (p->pgrp != -pid) - continue; - } - /* wait for cloned processes iff the __WCLONE flag is set */ - if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) - continue; - flag = 1; - switch (p->state) { - case TASK_STOPPED: - if (!p->exit_code) - continue; - if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED)) - continue; - read_unlock(&tasklist_lock); - retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; - if (!retval && stat_addr) - retval = put_user((p->exit_code << 8) | 0x7f, stat_addr); - if (!retval) { - p->exit_code = 0; - retval = p->pid; - } - goto end_wait4; - case TASK_ZOMBIE: - current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; - current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; - read_unlock(&tasklist_lock); - retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; - if (!retval && stat_addr) - retval = put_user(p->exit_code, stat_addr); - if (retval) - goto end_wait4; - retval = p->pid; - if (p->p_opptr != p->p_pptr) { - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(p); - p->p_pptr = p->p_opptr; - SET_LINKS(p); - write_unlock_irq(&tasklist_lock); - notify_parent(p, SIGCHLD); - } else - release(p); -#ifdef DEBUG_PROC_TREE - audit_ptree(); -#endif - goto end_wait4; - default: - continue; - } - } + SYS_WAIT4_SEARCH(current->p_cptr); + if (!flag && (current->flags & PF_CLWAIT)) + SYS_WAIT4_SEARCH(current->p_pptr->p_cptr); read_unlock(&tasklist_lock); if (flag) { retval = 0; @@ -488,6 +503,8 @@ retval = -ECHILD; end_wait4: remove_wait_queue(¤t->wait_chldexit,&wait); + if (current->flags & PF_CLWAIT) + remove_wait_queue(¤t->p_pptr->wait_chldexit,&wait_sib); return retval; } diff -ru clean-linux-2.2.10/kernel/fork.c linux-2.2.10/kernel/fork.c --- clean-linux-2.2.10/kernel/fork.c Mon Apr 12 12:44:26 1999 +++ linux-2.2.10/kernel/fork.c Thu Jul 29 10:08:13 1999 @@ -517,12 +517,18 @@ { unsigned long new_flags = p->flags; - new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK); + new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK + | PF_PPIDOK | PF_CLWAIT); new_flags |= PF_FORKNOEXEC; if (!(clone_flags & CLONE_PTRACE)) new_flags &= ~(PF_PTRACED|PF_TRACESYS); if (clone_flags & CLONE_VFORK) new_flags |= PF_VFORK; + if (clone_flags & CLONE_PPIDOK) + new_flags |= PF_PPIDOK; + if (clone_flags & CLONE_WAIT) + new_flags |= PF_CLWAIT; + p->flags = new_flags; } @@ -587,7 +593,14 @@ p->next_run = p; p->prev_run = p; - p->p_pptr = p->p_opptr = current; + if (!(clone_flags & CLONE_PPID)) { + p->p_pptr = p->p_opptr = current; + } else if (current->flags & PF_PPIDOK) { + p->p_pptr = p->p_opptr = current->p_opptr; + } else { + retval = -EPERM; + goto bad_fork_cleanup; + } p->p_cptr = NULL; init_waitqueue(&p->wait_chldexit); p->vfork_sem = NULL; @@ -668,7 +681,10 @@ p->next_run = NULL; p->prev_run = NULL; - wake_up_process(p); /* do this last */ + if (!(clone_flags & CLONE_SUSPENDED)) + wake_up_process(p); /* do this last */ + else + p->state = TASK_STOPPED; } ++total_forks; bad_fork: - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |