Subject: stopping childs (patch included)
To: None <tech-kern@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-kern
Date: 11/02/2002 00:45:04
Hi all

I frequently have the need to stop a process on fork or exec, for debugging
purposes. It can be done by tricking the process into an infinite loop, or by
adding somes hacks in the kernel to send a SIGSTOP at the right time.

Some support in the kernel to do this would be nice. My idea is to use a sysctl
to set a value (named p_stopchild) stored in struct proc:

$ sysctl -w proc.$$.stopchild=2                               
proc.291.stopchild: 0 -> 2
$ ls
Here, the shell gets blocked after the fork. It's possible to attach it, or to
send a SIGCONT. Once the process can continue after the fork, p_stopchild is
decreased. Because it does not reach zero, we will stop again after the shell
calls exec to become ls.

Find below a patch that does the job. Is it good enough to be committed?

Index: sys/proc.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/proc.h,v
retrieving revision 1.147
diff -r1.147 proc.h
189a190
>       int             p_stopchild;    /* Stop childs on fork and exec */
Index: sys/sysctl.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/sysctl.h,v
retrieving revision 1.78
diff -r1.78 sysctl.h
593c593,594
< #define       PROC_PID_MAXID          3
---
> #define       PROC_PID_STOPCHILD      3
> #define       PROC_PID_MAXID          4
598a600
>       { "stopchild", CTLTYPE_INT }, \
Index: kern/kern_sysctl.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_sysctl.c,v
retrieving revision 1.113
diff -r1.113 kern_sysctl.c
746a747,753
>       if (name[1] == PROC_PID_STOPCHILD) {
>               if (namelen != 2)
>                       return EINVAL;
>               error = sysctl_int(oldp, oldlenp, newp, 
>                   newlen, &ptmp->p_stopchild);
>               return error;
>       }
Index: kern/kern_exec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.160
diff -r1.160 kern_exec.c
740a741,753
> 
>       if (p->p_stopchild) {
>               int s;
> 
>               sigminusset(&contsigmask, &p->p_sigctx.ps_siglist);
>               SCHED_LOCK(s);
>               p->p_stopchild--;
>               p->p_stat = SSTOP;
>               mi_switch(p, NULL);
>               SCHED_ASSERT_UNLOCKED();
>               splx(s);
>       }
> 
Index: kern/kern_fork.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_fork.c,v
retrieving revision 1.96
diff -r1.96 kern_fork.c
474c474,475
<        * Make child runnable, set start time, and add to run queue.
---
>        * Make child runnable, set start time, and add to run queue
>        * except if the parent requested the child to start in SSTOP state.
479,480c480,487
<       p2->p_stat = SRUN;
<       setrunqueue(p2);
---
>       if (p1->p_stopchild) {
>               p2->p_stat = SSTOP;
>               p2->p_stopchild = p1->p_stopchild - 1;
>               p1->p_stopchild = 0;
>       } else {
>               p2->p_stat = SRUN;
>               setrunqueue(p2);
>       }


-- 
Emmanuel Dreyfus.
"Le 80x86 n'est pas si complexe - il n'a simplement pas de sens"
(Mike Johnson, responsable de la conception x86 chez AMD) 
manu@netbsd.org