From 1e656b349d31fee3b7f6c09a3eeba94b3439f60f Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 25 Oct 2006 11:29:43 +0000 Subject: [PATCH] . processes stay ZOMBIE, even after wait(), to avoid wrongly seeing them as living processes before they are cleaned up (fixes wait()/waitpid() hanging forever on previously-ZOMBIE processes) . stop processes from running using sys_nice() with PRIO_STOP when a handled signal is delivered, before computing stack locations for sys_sigsend(). (fixes race condition when runnable processes get signals, and e.g. get scheduled before FS sends a reply to unpause(), which can make the signal stack location wrong.) --- servers/pm/forkexit.c | 6 +++++- servers/pm/main.c | 4 ++-- servers/pm/mproc.h | 1 + servers/pm/signal.c | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index d12898a0f..4128656c1 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -326,6 +326,7 @@ int for_trace; 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) && rmp->mp_fs_call != PM_EXIT) { cleanup(rmp); } @@ -369,6 +370,7 @@ PUBLIC int do_waitpid() /* The value of pidarg determines which children qualify. */ if (pidarg > 0 && pidarg != rp->mp_pid) continue; if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue; + if (rp->mp_flags & TOLD_PARENT) continue; /* post-ZOMBIE */ children++; /* this child is acceptable */ if (rp->mp_flags & ZOMBIE) { @@ -430,6 +432,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 & TOLD_PARENT) + panic(__FILE__, "tell_parent: telling parent again", NO_NUM); parent = &mproc[mp_parent]; /* Wake up the parent by sending the reply message. */ @@ -437,7 +441,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; /* avoid informing parent twice */ + child->mp_flags |= TOLD_PARENT; /* avoid informing parent twice */ } /*===========================================================================* diff --git a/servers/pm/main.c b/servers/pm/main.c index 3f23a8566..58d66f34d 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -794,7 +794,7 @@ message *m_ptr; /* Clean up if the parent has collected the exit * status */ - if (!(rmp->mp_flags & ZOMBIE)) + if (rmp->mp_flags & TOLD_PARENT) real_cleanup(rmp); break; @@ -909,7 +909,7 @@ message *m_ptr; /* Clean up if the parent has collected the exit * status */ - if (!(rmp->mp_flags & ZOMBIE)) + if (rmp->mp_flags & TOLD_PARENT) real_cleanup(rmp); break; diff --git a/servers/pm/mproc.h b/servers/pm/mproc.h index 500c60a26..047de24af 100644 --- a/servers/pm/mproc.h +++ b/servers/pm/mproc.h @@ -84,6 +84,7 @@ EXTERN struct mproc { #define PRIV_PROC 0x2000 /* system process, special privileges */ #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 NIL_MPROC ((struct mproc *) 0) diff --git a/servers/pm/signal.c b/servers/pm/signal.c index 6332a12ef..5dbeb18b8 100644 --- a/servers/pm/signal.c +++ b/servers/pm/signal.c @@ -454,6 +454,8 @@ int signo; /* signal to send to process (1 to _NSIG) */ #endif sigflags = rmp->mp_sigact[signo].sa_flags; if (sigismember(&rmp->mp_catch, signo)) { + /* Stop process from running before we do stack calculations. */ + sys_nice(rmp->mp_endpoint, PRIO_STOP); if (rmp->mp_flags & SIGSUSPENDED) rmp->mp_sigmsg.sm_mask = rmp->mp_sigmask2; else -- 2.44.0