Index: linux/Documentation/Configure.help =================================================================== RCS file: /users/sychron/cvsroot/linux/Documentation/Configure.help,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.10.2.2 diff -u -r1.1.2.10 -r1.1.2.10.2.2 --- linux/Documentation/Configure.help 2001/08/24 11:19:25 1.1.2.10 +++ linux/Documentation/Configure.help 2001/09/11 12:26:01 1.1.2.10.2.2 @@ -18468,6 +18468,17 @@ To use this option, you have to check that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. +Process adoption +CONFIG_PROCESS_ADOPTION + + Enables additional process lineage code; when a process dies, its + children are adopted by the nearest surviving ancestor, rather than + than 1 (init), the traditional UNIX functionality. + + This is useful, for example, when tracking daemon processes where + the initial process forks a child and then exits - the orphaned + process is adopted by its grandparent rather than init. + # # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, Index: linux/arch/i386/config.in =================================================================== RCS file: /users/sychron/cvsroot/linux/arch/i386/config.in,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.6.2.1 diff -u -r1.1.2.6 -r1.1.2.6.2.1 --- linux/arch/i386/config.in 2001/08/16 18:37:48 1.1.2.6 +++ linux/arch/i386/config.in 2001/08/24 15:29:24 1.1.2.6.2.1 @@ -185,6 +185,7 @@ mainmenu_option next_comment comment 'General setup' +bool 'Process Adoption' CONFIG_PROCESS_ADOPTION bool 'Networking support' CONFIG_NET bool 'SGI Visual Workstation support' CONFIG_VISWS if [ "$CONFIG_VISWS" = "y" ]; then Index: linux/include/linux/sched.h =================================================================== RCS file: /users/sychron/cvsroot/linux/include/linux/sched.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.6.2.1 diff -u -r1.1.2.6 -r1.1.2.6.2.1 --- linux/include/linux/sched.h 2001/08/16 18:37:21 1.1.2.6 +++ linux/include/linux/sched.h 2001/08/24 15:29:24 1.1.2.6.2.1 @@ -401,6 +401,60 @@ u32 self_exec_id; /* Protection of (de-)allocation: mm, files, fs, tty */ spinlock_t alloc_lock; +#ifdef CONFIG_PROCESS_ADOPTION +/* PROCESS ADOPTION code Copyright Sychron Inc. 2001 - www.sychron.com */ +/* PROCESS ADOPTION code was written from scratch without reference to + * any part of Solaris or any other software. No reference was made to + * copyright material belonging to Sun Microsystems, Inc. other than + * publicly available information, specifically Mauro and McDougall + * "Solaris Internals", (Sun Microsystems Press / Prentice Hall ISBN + * 0-13-022496-0) + * + * p_nkptr - Next Of Kin; process's closest living ancestor + * p_adptr - Adopted Descendents (see below) + * p_pasptr - Previous Adopted Sibling (in Next Of Kin's AD list) + * p_nasptr - Next Adopted Sibling (in Next Of Kin's AD list) + * + * These fields are used by the accompanying code patches to + * kernel/{fork,exit}.c to implement process adoption in a similar + * style to Sun's Solaris. Orphaned processes are adopted by their + * closest surviving ancestor, whereas traditional U**X functionality + * (p_cptr, p_pptr, p_ysptr, p_osptr) is that orphan processes are + * adopted by init (pid 1). With daemons, the initial process exits + * almost immediately; much better if the running daemon can be traced + * back to the shell which invoked its parent. + * + * Solaris equivalents are... + * p_nkptr = nextofkin + * p_adptr = orphan + * p_nasptr = nextorph + * [ p_pasptr has no Solaris equivalent, as its list is singly linked ] + * + * p_adptr is a pointer to a doubly-linked list (similar to p_cptr) of + * the process's descendents which have no other next of kin. The list + * includes the process's own children (duplicating the p_cptr list), + * and orphaned grandchildren adopted when a child died. Solaris's + * "nextofkin" seems a reasonable term - one is next of kin to one's + * own children as well as those one adopts. However, Solaris's + * "orphan" is just plain wrong - one's own children are clearly not + * orphans while one lives. "Descendent" seems equally wrong, since + * grandchildren with running parents are descendents (as are *their* + * descendents), but clearly should not be in this list. We use + * "Adopted Descendents" (ADs); if regarding one's own children as + * "adopted" seems odd, consider them implicitly adopted at birth as + * distinct from orphaned grandchildren explicitly adopted later. + * + * p_pasptr and p_nasptr do not have the same younger and older + * semantics as p_ysptr and p_osptr. Position in the list reflects + * when their parent died, not their creation time, so they are + * referred to as previous and next to discourage assumptions about + * age order. p_adptr points to the most recently adopted process; the + * list is traversed via p_nasptr, so the "next" adopted sibling was + * adopted *before* its predecessor, like the Solaris nextorph order. + * + */ + struct task_struct *p_nkptr, *p_dptr, *p_pdptr, *p_ndptr; +#endif }; /* @@ -437,6 +491,16 @@ #define MAX_COUNTER (20*HZ/100) #define DEF_NICE (0) +#ifdef CONFIG_PROCESS_ADOPTION +#define INIT_TASK_ADOPTION \ + p_nkptr: (&init_task), \ + p_adptr: NULL, \ + p_pasptr: NULL, \ + p_nasptr: NULL, +#else +#define INIT_TASK_ADOPTION +#endif + /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -479,7 +543,8 @@ sig: &init_signals, \ pending: { NULL, &tsk.pending.head, {{0}}}, \ blocked: {{0}}, \ - alloc_lock: SPIN_LOCK_UNLOCKED \ + alloc_lock: SPIN_LOCK_UNLOCKED, \ + INIT_TASK_ADOPTION } Index: linux/kernel/exit.c =================================================================== RCS file: /users/sychron/cvsroot/linux/kernel/exit.c,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.4.2.1 diff -u -r1.1.2.4 -r1.1.2.4.2.1 --- linux/kernel/exit.c 2001/08/24 11:17:16 1.1.2.4 +++ linux/kernel/exit.c 2001/08/24 15:29:24 1.1.2.4.2.1 @@ -418,6 +418,35 @@ write_lock_irq(&tasklist_lock); } } +#ifdef CONFIG_PROCESS_ADOPTION + /* PROCESS ADOPTION code Copyright Sychron Inc. 2001 - www.sychron.com */ + /* Please see include/linux/sched.h */ + + /* Remove current from its next-of-kin's Adopted Descendent list */ + if (current->p_pasptr != NULL) + current->p_pasptr->p_nasptr = current->p_nasptr; + else + current->p_nkptr->p_adptr = current->p_nasptr; + if (current->p_nasptr != NULL) + current->p_nasptr->p_pasptr = current->p_pasptr; + + /* If current has an AD list, pass them up to current's next of kin */ + if (current->p_adptr) { + /* For each of current's ADs, set the next of kin to + * be its (current's) next of kin. */ + struct task_struct *p, *last_AD; + for (p = last_AD = current->p_adptr; p; p = p->p_nasptr) { + p->p_nkptr = current->p_nkptr; + last_AD = p; + } + /* Link current's AD list into its (current's) + * next-of-kin's AD list */ + last_AD->p_nasptr = current->p_nkptr->p_adptr; + if (current->p_nkptr->p_adptr) + current->p_nkptr->p_adptr->p_pasptr = last_AD; + current->p_nkptr->p_adptr = current->p_adptr; + } +#endif write_unlock_irq(&tasklist_lock); } Index: linux/kernel/fork.c =================================================================== RCS file: /users/sychron/cvsroot/linux/kernel/fork.c,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.7.2.1 diff -u -r1.1.2.7 -r1.1.2.7.2.1 --- linux/kernel/fork.c 2001/08/16 18:37:20 1.1.2.7 +++ linux/kernel/fork.c 2001/08/24 15:29:24 1.1.2.7.2.1 @@ -610,6 +610,18 @@ p->run_list.prev = NULL; p->p_cptr = NULL; +#ifdef CONFIG_PROCESS_ADOPTION + /* PROCESS ADOPTION code Copyright Sychron Inc. 2001 - www.sychron.com */ + /* Please see include/linux/sched.h */ + + p->p_nkptr = current; /* Current is the new child's next of kin */ + p->p_adptr = NULL; /* The new child has no Adopted Descendents */ + p->p_pasptr = NULL; /* The new child is first in the AD list (no predecessors) */ + p->p_nasptr = current->p_adptr; /* The new child's successor is the head of current's AD list */ + if (current->p_adptr) /* If current has an existing AD list, */ + current->p_adptr->p_pasptr = p; /* the new child becomes its predecessor */ + current->p_adptr = p; /* The new child becomes the head of current's AD list */ +#endif init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; if (clone_flags & CLONE_VFORK) {