]> Zhao Yanbai Git Server - minix.git/commitdiff
PM: add EXITING process flag as stopgap between starting coredump and setting ZOMBIE...
authorDavid van Moolenbroek <david@minix3.org>
Thu, 9 Jul 2009 22:33:56 +0000 (22:33 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 9 Jul 2009 22:33:56 +0000 (22:33 +0000)
servers/pm/forkexit.c
servers/pm/main.c
servers/pm/misc.c
servers/pm/mproc.h
servers/pm/signal.c
servers/pm/trace.c

index 08bbc3193925af538099a8eb883f6c7f0f693eb6..f5e531794d1f52e8a166187ede237933e9ae3f38 100644 (file)
@@ -271,6 +271,11 @@ int exit_type;                     /* one of PM_EXIT, PM_EXIT_TR, PM_DUMPCORE */
        return;
   }
 
+  /* The process is now officially exiting. The ZOMBIE flag is not enough, as
+   * it is not set here for core dumps - introducing potential race conditions.
+   */
+  rmp->mp_flags |= EXITING;
+
   /* Pending reply messages for the dead process cannot be delivered. */
   rmp->mp_flags &= ~REPLY;
 
@@ -290,8 +295,7 @@ int exit_type;                      /* one of PM_EXIT, PM_EXIT_TR, PM_DUMPCORE */
                /* 'rmp' now points to a child to be disinherited. */
                rmp->mp_parent = INIT_PROC_NR;
                parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
-               if (parent_waiting && (rmp->mp_flags & ZOMBIE) &&
-                       !(rmp->mp_flags & TOLD_PARENT)) {
+               if (parent_waiting && (rmp->mp_flags & ZOMBIE)) {
                        tell_parent(rmp);
 
                        if (rmp->mp_fs_call == PM_IDLE)
@@ -427,7 +431,7 @@ struct mproc *rmp;
   if (rmp->mp_flags & ZOMBIE)
        panic(__FILE__, "zombify: process was already a zombie", NO_NUM);
 
-  rmp->mp_flags &= (IN_USE|PRIV_PROC);
+  rmp->mp_flags &= (IN_USE|PRIV_PROC|EXITING);
   rmp->mp_flags |= ZOMBIE;
 
   p_mp = &mproc[rmp->mp_parent];
@@ -454,6 +458,8 @@ register struct mproc *child;       /* tells which process is exiting */
   mp_parent= child->mp_parent;
   if (mp_parent <= 0)
        panic(__FILE__, "tell_parent: bad value in mp_parent", mp_parent);
+  if(!(child->mp_flags & ZOMBIE))
+       panic(__FILE__, "tell_parent: child not a zombie", NO_NUM);
   if(child->mp_flags & TOLD_PARENT)
        panic(__FILE__, "tell_parent: telling parent again", NO_NUM);
   parent = &mproc[mp_parent];
@@ -463,6 +469,7 @@ register struct mproc *child;       /* tells which process is exiting */
   parent->mp_reply.reply_res2 = exitstatus;
   setreply(child->mp_parent, child->mp_pid);
   parent->mp_flags &= ~WAITING;                /* parent no longer waiting */
+  child->mp_flags &= ~ZOMBIE;          /* child no longer a zombie */
   child->mp_flags |= TOLD_PARENT;      /* avoid informing parent twice */
 }
 
index 130e068378c0ba9172c394a023d4a1e6770b862d..bd083e532ec05c490fd2e6c457f7ee26c2efc31e 100644 (file)
@@ -148,9 +148,9 @@ PUBLIC int main()
                /* In the meantime, the process may have been killed by a
                 * signal (e.g. if a lethal pending signal was unblocked)
                 * without the PM realizing it. If the slot is no longer in
-                * use or just a zombie, don't try to reply.
+                * use or the process is exiting, don't try to reply.
                 */
-               if ((rmp->mp_flags & (REPLY | IN_USE | ZOMBIE)) ==
+               if ((rmp->mp_flags & (REPLY | IN_USE | EXITING)) ==
                   (REPLY | IN_USE)) {
                        s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
                        if (s != OK) {
@@ -365,7 +365,7 @@ void checkme(char *str, int line)
        int boned = 0;
        int proc_nr;
        for (proc_nr=0, trmp=mproc; proc_nr < NR_PROCS; proc_nr++, trmp++) {
-               if ((trmp->mp_flags & (REPLY | IN_USE | ZOMBIE)) ==
+               if ((trmp->mp_flags & (REPLY | IN_USE | EXITING)) ==
                   (REPLY | IN_USE)) {
                        int tp;
                        if(pm_isokendpt(trmp->mp_endpoint, &tp) != OK) {
index 551cac882a8dd3cc984dd142f2be231100b70db5..cc04c19040126a85fd9f1cb9c54013adfe009c9e 100644 (file)
@@ -343,7 +343,7 @@ PUBLIC int do_getprocnr()
                return(s);
        search_key[key_len] = '\0';     /* terminate for safety */
        for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
-               if (((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE) && 
+               if (((rmp->mp_flags & (IN_USE | EXITING)) == IN_USE) && 
                        strncmp(rmp->mp_name, search_key, key_len)==0) {
                        mp->mp_reply.endpt = rmp->mp_endpoint;
                        printf("PM: name %s result: %d\n", search_key, 
index a0e961345edee9c251138b7a1b48e65b40a988a1..2dce02e0258ec071a626593c89ff7e4d9982a72c 100644 (file)
@@ -65,7 +65,7 @@ EXTERN struct mproc {
 /* Flag values */
 #define IN_USE          0x001  /* set when 'mproc' slot in use */
 #define WAITING         0x002  /* set by WAIT system call */
-#define ZOMBIE          0x004  /* set by EXIT, cleared by WAIT */
+#define ZOMBIE          0x004  /* waiting for parent to issue WAIT call */
 #define PAUSED          0x008  /* set by PAUSE system call */
 #define ALARM_ON        0x010  /* set when SIGALRM timer started */
 #define        TRACED          0x040   /* set if process is to be traced */
@@ -76,6 +76,7 @@ EXTERN struct mproc {
 #define PM_SIG_PENDING 0x4000  /* process got a signal while waiting for FS */
 #define PARTIAL_EXEC   0x8000  /* Process got a new map but no content */
 #define TOLD_PARENT   0x10000  /* Parent wait() completed, ZOMBIE off */
+#define EXITING       0x20000  /* set by EXIT, process is now exiting */
 
 #define NIL_MPROC ((struct mproc *) 0)
 
index f43e338309cd856bb846f2ac59b43174192a93f2..21d8d31c632e6d03e6ab4ca9687101e3aa197eca 100644 (file)
@@ -230,7 +230,7 @@ PUBLIC int ksig_pending()
        /* If the process still exists to the kernel after the signal
         * has been handled ...
         */
-        if ((mproc[proc_nr_p].mp_flags & (IN_USE | ZOMBIE)) == IN_USE)
+        if ((mproc[proc_nr_p].mp_flags & (IN_USE | EXITING)) == IN_USE)
        {
           if((r=sys_endksig(proc_nr_e)) != OK) /* ... tell kernel it's done */
                panic(__FILE__,"sys_endksig failed", r);
@@ -256,8 +256,8 @@ sigset_t sig_map;
        return;
   }
   rmp = &mproc[proc_nr];
-  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
-       printf("PM: handle_ksig: %d?? zombie / not in use\n", proc_nr_e);
+  if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
+       printf("PM: handle_ksig: %d?? exiting / not in use\n", proc_nr_e);
        return;
   }
   proc_id = rmp->mp_pid;
@@ -379,7 +379,7 @@ struct timer *tp;
 
   rmp = &mproc[proc_nr_n];
 
-  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return;
+  if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) return;
   if ((rmp->mp_flags & ALARM_ON) == 0) return;
   rmp->mp_flags &= ~ALARM_ON;
   check_sig(rmp->mp_pid, SIGALRM);
@@ -424,9 +424,8 @@ int signo;                  /* signal to send to process (1 to _NSIG) */
   int exit_type;
 
   slot = (int) (rmp - mproc);
-  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
-       printf("PM: signal %d sent to %s process %d\n",
-               signo, (rmp->mp_flags & ZOMBIE) ? "zombie" : "dead", slot);
+  if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
+       printf("PM: signal %d sent to exiting process %d\n", signo, slot);
        panic(__FILE__,"", NO_NUM);
   }
   if (rmp->mp_fs_call != PM_IDLE || rmp->mp_fs_call2 != PM_IDLE)
@@ -551,13 +550,12 @@ int signo;                        /* signal to send to process (0 to _NSIG) */
   if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
 
   /* Search the proc table for processes to signal.  
-   * (See forkexit.c aboutpid magic.)
+   * (See forkexit.c about pid magic.)
    */
   count = 0;
   error_code = ESRCH;
   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
        if (!(rmp->mp_flags & IN_USE)) continue;
-       if ((rmp->mp_flags & ZOMBIE) && signo != 0) continue;
 
        /* Check for selection. */
        if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
@@ -580,7 +578,7 @@ int signo;                  /* signal to send to process (0 to _NSIG) */
        }
 
        count++;
-       if (signo == 0) continue;
+       if (signo == 0 || (rmp->mp_flags & EXITING)) continue;
 
        /* 'sig_proc' will handle the disposition of the signal.  The
         * signal may be caught, blocked, ignored, or cause process
@@ -592,7 +590,7 @@ int signo;                  /* signal to send to process (0 to _NSIG) */
   }
 
   /* If the calling process has killed itself, don't reply. */
-  if ((mp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return(SUSPEND);
+  if ((mp->mp_flags & (IN_USE | EXITING)) != IN_USE) return(SUSPEND);
   return(count > 0 ? OK : error_code);
 }
 
index 8e8622c959d77c47c3b635b0719c810e409c6fa0..3a0e1c7a2fe1ef8de5afc0d4352030337e2851ed 100644 (file)
@@ -144,7 +144,7 @@ pid_t lpid;
   register struct mproc *rmp;
 
   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
-       if ((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE &&
+       if ((rmp->mp_flags & (IN_USE | EXITING)) == IN_USE &&
                rmp->mp_pid == lpid) {
                return(rmp);
        }