* process.c [LINUX] (internal_fork): Move the code to attach a new
child process into a new function internal_fork_child.  This is
called at the end of fork/vfork/clone, when the syscall is returning.
This should not change any behaviour.  It is a preparation for a later
change which uses PTRACE_EVENT_{FORK,VFORK,CLONE} and needs the new
function to be separate.
* process.c [LINUX] (internal_fork_child): New function.
* defs.h [LINUX] (internal_fork_child): Declare.
* defs.h (struct tcb): Rearrange so the LINUX ifdef can omit ->baddr.

Signed-off-by: Jamie Lokier <ja...@shareable.org>
---
 defs.h    |    9 ++-
 process.c |  174 ++++++++++++++++++++++++++++++++----------------------------
 2 files changed, 99 insertions(+), 84 deletions(-)

diff --git a/defs.h b/defs.h
index 62b3719..7ce1fa6 100644
--- a/defs.h
+++ b/defs.h
@@ -331,10 +331,10 @@ struct tcb {
        int nclone_threads;     /* # of nchildren with CLONE_THREAD */
        int nclone_detached;    /* # of nchildren with CLONE_DETACHED */
        int nclone_waiting;     /* clone threads in wait4 (TCB_SUSPENDED) */
-#endif
-                               /* (1st arg of wait4()) */
+#else
        long baddr;             /* `Breakpoint' address */
-       long inst[2];           /* Instructions on above */
+#endif
+       long inst[2];           /* Instructions on breakpoint */
        int pfd;                /* proc file descriptor */
 #ifdef SVR4
 #ifdef HAVE_MP_PROCFS
@@ -535,6 +535,9 @@ extern const char *sprint_open_modes(mode_t);
 extern int is_restart_error(struct tcb *);
 
 extern int change_syscall(struct tcb *, int);
+#ifdef LINUX
+extern int internal_fork_child(struct tcb *, int);
+#endif
 extern int internal_fork(struct tcb *);
 extern int internal_exec(struct tcb *);
 extern int internal_wait(struct tcb *, int);
diff --git a/process.c b/process.c
index 6ae08a9..645f2c4 100644
--- a/process.c
+++ b/process.c
@@ -788,6 +788,97 @@ change_syscall(struct tcb *tcp, int new)
 }
 
 #ifdef LINUX
+/*
+ * Called when we learn about a child process and know which parent
+ * it's from.  (Dubiously, pid here is int because alloctcb() uses it,
+ * but syscall return values are unsigned long and could overflow.)
+ */
+int
+internal_fork_child(struct tcb *tcp, int pid)
+{
+       struct tcb *tcpchild;
+       int clone_flags;
+
+       tcpchild = pid2tcb(pid);
+       if (tcpchild != NULL) {
+               /* The child already reported its startup trap before
+                  the parent reported its syscall return or PTRACE_EVENT.  */
+               if ((tcpchild->flags
+                    & (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
+                   != (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
+                       fprintf(stderr, "\
+[preattached child %d of %d in weird state!]\n",
+                               pid, tcp->pid);
+       } else {
+               fork_tcb(tcp);
+               tcpchild = alloctcb(pid);
+       }
+
+       tcpchild->flags |= TCB_ATTACHED;
+
+       if ((tcp->flags & TCB_CLONE_THREAD) && tcp->parent != NULL) {
+               /*
+                * The parent in this clone is itself a thread belonging to
+                * another process.  There is no meaning to the parentage
+                * relationship of the new child with the thread, only with
+                * the process.  We associate the new thread with our
+                * parent.  Since this is done for every new thread, there
+                * will never be a TCB_CLONE_THREAD process that has
+                * children.
+                */
+               tcpchild->parent = tcp->parent;
+       } else {
+               tcpchild->parent = tcp;
+       }
+       ++(tcpchild->parent)->nchildren;
+
+       /* Set by setbpt. */
+       clone_flags = tcp->u_arg[ARG_FLAGS];
+
+       if (clone_flags & CLONE_THREAD) {
+               tcpchild->flags |= TCB_CLONE_THREAD;
+               ++(tcpchild->parent)->nclone_threads;
+       }
+       if (clone_flags & CLONE_DETACHED) {
+               tcpchild->flags |= TCB_CLONE_DETACHED;
+               ++(tcpchild->parent)->nclone_detached;
+       }
+
+       /* Child has BPT too, must be removed on first child stop. */
+       if (tcp->flags & TCB_BPTSET) {
+               tcpchild->flags |= TCB_BPTSET;
+               memcpy(tcpchild->inst, tcp->inst, sizeof tcpchild->inst);
+               if (clearbpt(tcp))
+                       return -1;
+       }
+
+       if (tcpchild->flags & TCB_SUSPENDED) {
+               /*
+                * The child was born suspended, due to our having used
+                * CLONE_PTRACE and the child event happened before getting
+                * the pid from the parent.
+                */
+               if (tcpchild->flags & TCB_BPTSET)
+                       if (clearbpt(tcpchild))
+                               return -1;
+
+               tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
+               if (ptrace_restart(PTRACE_SYSCALL, tcpchild, 0) < 0)
+                       return -1;
+
+               if (!qflag)
+                       fprintf(stderr, "\
+Process %u resumed (parent %d ready)\n",
+                               pid, tcp->pid);
+       } else {
+               if (!qflag)
+                       fprintf(stderr, "\
+Process %d attached\n", pid);
+       }
+
+       return 0;
+}
+
 int
 internal_fork(struct tcb *tcp)
 {
@@ -798,10 +889,7 @@ internal_fork(struct tcb *tcp)
                if (setbpt(tcp) < 0)
                        return 0;
        } else {
-               struct tcb *tcpchild;
-               int pid;
-               int bpt;
-               int call_flags;
+               int pid, bpt;
 
                if (!(tcp->flags & TCB_FOLLOWFORK))
                        return 0;
@@ -816,83 +904,7 @@ internal_fork(struct tcb *tcp)
 
                pid = tcp->u_rval;
 
-               tcpchild = pid2tcb(pid);
-               if (tcpchild != NULL) {
-                       /* The child already reported its startup trap
-                          before the parent reported its syscall return.  */
-                       if ((tcpchild->flags
-                            & (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
-                           != (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
-                               fprintf(stderr, "\
-[preattached child %d of %d in weird state!]\n",
-                                       pid, tcp->pid);
-               } else {
-                       fork_tcb(tcp);
-                       tcpchild = alloctcb(pid);
-               }
-
-               if (bpt)
-                       clearbpt(tcp);
-
-               tcpchild->flags |= TCB_ATTACHED;
-               /* Child has BPT too, must be removed on first occasion.  */
-               if (bpt) {
-                       tcpchild->flags |= TCB_BPTSET;
-                       tcpchild->baddr = tcp->baddr;
-                       memcpy(tcpchild->inst, tcp->inst,
-                               sizeof tcpchild->inst);
-               }
-               tcpchild->parent = tcp;
-               tcp->nchildren++;
-               if (tcpchild->flags & TCB_SUSPENDED) {
-                       /* The child was born suspended, due to our having
-                          forced CLONE_PTRACE.  */
-                       if (bpt)
-                               clearbpt(tcpchild);
-
-                       tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
-                       if (ptrace_restart(PTRACE_SYSCALL, tcpchild, 0) < 0)
-                               return -1;
-
-                       if (!qflag)
-                               fprintf(stderr, "\
-Process %u resumed (parent %d ready)\n",
-                                       pid, tcp->pid);
-               }
-               else {
-                       if (!qflag)
-                               fprintf(stderr, "Process %d attached\n", pid);
-               }
-
-               /*
-                * Save the flags used in this call,
-                * in case we point TCP to our parent below.
-                */
-               call_flags = tcp->u_arg[ARG_FLAGS];
-               if ((tcp->flags & TCB_CLONE_THREAD) &&
-                   tcp->parent != NULL) {
-                 /*
-                  * The parent in this clone is itself a thread belonging
-                  * to another process.  There is now meaning to the
-                  * parentage relationship of the new child with the
-                  * thread, only with the process.  We associate the new
-                  * thread with our parent.  Since this is done for every
-                  * new thread, there will never be a TCB_CLONE_THREAD
-                  * process that has children.
-                  */
-                 --tcp->nchildren;
-                 tcp = tcp->parent;
-                 tcpchild->parent = tcp;
-                 ++tcp->nchildren;
-               }
-               if (call_flags & CLONE_THREAD) {
-                 tcpchild->flags |= TCB_CLONE_THREAD;
-                 ++tcp->nclone_threads;
-               }
-               if (call_flags & CLONE_DETACHED) {
-                 tcpchild->flags |= TCB_CLONE_DETACHED;
-                 ++tcp->nclone_detached;
-               }
+               return internal_fork_child(tcp, pid);
        }
        return 0;
 }
-- 
1.7.0.4

_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to