PM cleanup: merge exit and coredump paths
This commit is contained in:
parent
5e173f55f5
commit
67d986f882
|
@ -162,7 +162,7 @@ int result;
|
|||
|
||||
/* Use SIGILL signal that something went wrong */
|
||||
rmp->mp_sigstatus = SIGILL;
|
||||
pm_exit(rmp, 0, FALSE /*!for_trace*/);
|
||||
exit_proc(rmp, 0, PM_EXIT);
|
||||
return;
|
||||
}
|
||||
setreply(rmp-mproc, result);
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
* exits first, it continues to occupy a slot until the parent does a WAIT.
|
||||
*
|
||||
* The entry points into this file are:
|
||||
* do_fork: perform the FORK system call
|
||||
* do_pm_exit: perform the EXIT system call (by calling pm_exit())
|
||||
* pm_exit: actually do the exiting
|
||||
* do_wait: perform the WAITPID or WAIT system call
|
||||
* tell_parent: tell parent about the death of a child
|
||||
* do_fork: perform the FORK system call
|
||||
* do_fork_nb: special nonblocking version of FORK, for RS
|
||||
* do_exit: perform the EXIT system call (by calling exit_proc())
|
||||
* exit_proc: actually do the exiting, and tell FS about it
|
||||
* exit_restart: continue exiting a process after FS has replied
|
||||
* do_waitpid: perform the WAITPID or WAIT system call
|
||||
*/
|
||||
|
||||
#include "pm.h"
|
||||
|
@ -26,7 +27,9 @@
|
|||
|
||||
#define LAST_FEW 2 /* last few slots reserved for superuser */
|
||||
|
||||
FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
|
||||
FORWARD _PROTOTYPE (void zombify, (struct mproc *rmp) );
|
||||
FORWARD _PROTOTYPE (void tell_parent, (struct mproc *child) );
|
||||
FORWARD _PROTOTYPE (void cleanup, (register struct mproc *rmp) );
|
||||
|
||||
/*===========================================================================*
|
||||
* do_fork *
|
||||
|
@ -173,35 +176,45 @@ PUBLIC int do_fork_nb()
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_pm_exit *
|
||||
* do_exit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_pm_exit()
|
||||
PUBLIC int do_exit()
|
||||
{
|
||||
/* Perform the exit(status) system call. The real work is done by pm_exit(),
|
||||
/* Perform the exit(status) system call. The real work is done by exit_proc(),
|
||||
* which is also called when a process is killed by a signal.
|
||||
*/
|
||||
pm_exit(mp, m_in.status, FALSE /*!for_trace*/);
|
||||
exit_proc(mp, m_in.status, PM_EXIT);
|
||||
return(SUSPEND); /* can't communicate from beyond the grave */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pm_exit *
|
||||
* exit_proc *
|
||||
*===========================================================================*/
|
||||
PUBLIC void pm_exit(rmp, exit_status, for_trace)
|
||||
PUBLIC void exit_proc(rmp, exit_status, exit_type)
|
||||
register struct mproc *rmp; /* pointer to the process to be terminated */
|
||||
int exit_status; /* the process' exit status (for parent) */
|
||||
int for_trace;
|
||||
int exit_type; /* one of PM_EXIT, PM_EXIT_TR, PM_DUMPCORE */
|
||||
{
|
||||
/* A process is done. Release most of the process' possessions. If its
|
||||
* parent is waiting, release the rest, else keep the process slot and
|
||||
* become a zombie.
|
||||
*/
|
||||
register int proc_nr, proc_nr_e;
|
||||
int parent_waiting, right_child, r;
|
||||
pid_t pidarg, procgrp;
|
||||
int parent_waiting, r;
|
||||
pid_t procgrp;
|
||||
struct mproc *p_mp;
|
||||
clock_t user_time, sys_time;
|
||||
|
||||
/* Do not create core files for set uid execution */
|
||||
if (exit_type == PM_DUMPCORE && rmp->mp_realuid != rmp->mp_effuid)
|
||||
exit_type = PM_EXIT;
|
||||
|
||||
/* System processes are destroyed before informing FS, meaning that FS can
|
||||
* not get their CPU state, so we can't generate a coredump for them either.
|
||||
*/
|
||||
if (exit_type == PM_DUMPCORE && (rmp->mp_flags & PRIV_PROC))
|
||||
exit_type = PM_EXIT;
|
||||
|
||||
proc_nr = (int) (rmp - mproc); /* get process slot number */
|
||||
proc_nr_e = rmp->mp_endpoint;
|
||||
|
||||
|
@ -213,7 +226,7 @@ int for_trace;
|
|||
|
||||
/* Do accounting: fetch usage times and accumulate at parent. */
|
||||
if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)
|
||||
panic(__FILE__,"pm_exit: sys_times failed", r);
|
||||
panic(__FILE__,"exit_proc: sys_times failed", r);
|
||||
|
||||
p_mp = &mproc[rmp->mp_parent]; /* process' parent */
|
||||
p_mp->mp_child_utime += user_time + rmp->mp_child_utime; /* add user time */
|
||||
|
@ -227,7 +240,7 @@ int for_trace;
|
|||
*/
|
||||
sys_nice(proc_nr_e, PRIO_STOP); /* stop the process */
|
||||
if((r=vm_willexit(proc_nr_e)) != OK) {
|
||||
panic(__FILE__, "pm_exit: vm_willexit failed", r);
|
||||
panic(__FILE__, "exit_proc: vm_willexit failed", r);
|
||||
}
|
||||
|
||||
if (proc_nr_e == INIT_PROC_NR)
|
||||
|
@ -240,16 +253,16 @@ int for_trace;
|
|||
{
|
||||
/* Tell FS about the exiting process. */
|
||||
if (rmp->mp_fs_call != PM_IDLE)
|
||||
panic(__FILE__, "pm_exit: not idle", rmp->mp_fs_call);
|
||||
rmp->mp_fs_call= (for_trace ? PM_EXIT_TR : PM_EXIT);
|
||||
panic(__FILE__, "exit_proc: not idle", rmp->mp_fs_call);
|
||||
rmp->mp_fs_call= exit_type;
|
||||
r= notify(FS_PROC_NR);
|
||||
if (r != OK) panic(__FILE__, "pm_exit: unable to notify FS", r);
|
||||
if (r != OK) panic(__FILE__, "exit_proc: unable to notify FS", r);
|
||||
|
||||
if (rmp->mp_flags & PRIV_PROC)
|
||||
{
|
||||
/* destroy system processes without waiting for FS */
|
||||
if((r= sys_exit(rmp->mp_endpoint)) != OK)
|
||||
panic(__FILE__, "pm_exit: sys_exit failed", r);
|
||||
panic(__FILE__, "exit_proc: sys_exit failed", r);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -264,18 +277,12 @@ int for_trace;
|
|||
/* Keep the process around until FS is finished with it. */
|
||||
|
||||
rmp->mp_exitstatus = (char) exit_status;
|
||||
pidarg = p_mp->mp_wpid; /* who's being waited for? */
|
||||
parent_waiting = p_mp->mp_flags & WAITING;
|
||||
right_child = /* child meets one of the 3 tests? */
|
||||
(pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp);
|
||||
|
||||
if (parent_waiting && right_child) {
|
||||
tell_parent(rmp); /* tell parent */
|
||||
} else {
|
||||
rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
|
||||
rmp->mp_flags |= ZOMBIE; /* parent not waiting, zombify child */
|
||||
sig_proc(p_mp, SIGCHLD); /* send parent a "child died" signal */
|
||||
}
|
||||
/* For normal exits, try to notify the parent as soon as possible.
|
||||
* For core dumps, notify the parent only once the core dump has been made.
|
||||
*/
|
||||
if (exit_type != PM_DUMPCORE)
|
||||
zombify(rmp);
|
||||
|
||||
/* If the process has children, disinherit them. INIT is the new parent. */
|
||||
for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
|
||||
|
@ -284,9 +291,11 @@ 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);
|
||||
!(rmp->mp_flags & TOLD_PARENT)) {
|
||||
tell_parent(rmp);
|
||||
|
||||
if (rmp->mp_fs_call == PM_IDLE)
|
||||
cleanup(rmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,6 +304,46 @@ int for_trace;
|
|||
if (procgrp != 0) check_sig(-procgrp, SIGHUP);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* exit_restart *
|
||||
*===========================================================================*/
|
||||
PUBLIC void exit_restart(rmp, reply_type)
|
||||
struct mproc *rmp; /* pointer to the process being terminated */
|
||||
int reply_type; /* one of PM_EXIT_REPLY(_TR), PM_CORE_REPLY */
|
||||
{
|
||||
/* FS replied to our exit or coredump request. Perform the second half of the
|
||||
* exit code.
|
||||
*/
|
||||
int r;
|
||||
|
||||
/* For core dumps, now is the right time to try to contact the parent. */
|
||||
if (reply_type == PM_CORE_REPLY)
|
||||
zombify(rmp);
|
||||
|
||||
if (!(rmp->mp_flags & PRIV_PROC))
|
||||
{
|
||||
/* destroy the (user) process */
|
||||
if((r=sys_exit(rmp->mp_endpoint)) != OK)
|
||||
panic(__FILE__, "exit_restart: sys_exit failed", r);
|
||||
}
|
||||
|
||||
/* Release the memory occupied by the child. */
|
||||
if((r=vm_exit(rmp->mp_endpoint)) != OK) {
|
||||
panic(__FILE__, "exit_restart: vm_exit failed", r);
|
||||
}
|
||||
|
||||
if (reply_type == PM_EXIT_REPLY_TR && rmp->mp_parent != INIT_PROC_NR)
|
||||
{
|
||||
/* Wake up the parent, completing the ptrace(T_EXIT) call */
|
||||
mproc[rmp->mp_parent].mp_reply.reply_trace = 0;
|
||||
setreply(rmp->mp_parent, OK);
|
||||
}
|
||||
|
||||
/* Clean up if the parent has collected the exit status */
|
||||
if (rmp->mp_flags & TOLD_PARENT)
|
||||
cleanup(rmp);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_waitpid *
|
||||
*===========================================================================*/
|
||||
|
@ -305,7 +354,7 @@ PUBLIC int do_waitpid()
|
|||
* really wait.
|
||||
* A process calling WAIT never gets a reply in the usual way at the end
|
||||
* of the main loop (unless WNOHANG is set or no qualifying child exists).
|
||||
* If a child has already exited, the routine cleanup() sends the reply
|
||||
* If a child has already exited, the routine tell_parent() sends the reply
|
||||
* to awaken the caller.
|
||||
* Both WAIT and WAITPID are handled by this code.
|
||||
*/
|
||||
|
@ -335,7 +384,7 @@ PUBLIC int do_waitpid()
|
|||
/* This child meets the pid test and has exited. */
|
||||
tell_parent(rp); /* this child has already exited */
|
||||
if (rp->mp_fs_call == PM_IDLE)
|
||||
real_cleanup(rp);
|
||||
cleanup(rp);
|
||||
return(SUSPEND);
|
||||
}
|
||||
if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
|
||||
|
@ -363,27 +412,40 @@ PUBLIC int do_waitpid()
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cleanup *
|
||||
* zombify *
|
||||
*===========================================================================*/
|
||||
PRIVATE void cleanup(child)
|
||||
register struct mproc *child; /* tells which process is exiting */
|
||||
PRIVATE void zombify(rmp)
|
||||
struct mproc *rmp;
|
||||
{
|
||||
/* Finish off the exit of a process. The process has exited or been killed
|
||||
* by a signal, and its parent is waiting.
|
||||
/* Zombify a process. If the parent is waiting, notify it immediately.
|
||||
* Otherwise, send a SIGCHLD signal to the parent.
|
||||
*/
|
||||
struct mproc *p_mp;
|
||||
int parent_waiting, right_child;
|
||||
pid_t pidarg;
|
||||
|
||||
if (child->mp_fs_call != PM_IDLE)
|
||||
panic(__FILE__, "cleanup: not idle", child->mp_fs_call);
|
||||
if (rmp->mp_flags & ZOMBIE)
|
||||
panic(__FILE__, "zombify: process was already a zombie", NO_NUM);
|
||||
|
||||
tell_parent(child);
|
||||
real_cleanup(child);
|
||||
rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
|
||||
rmp->mp_flags |= ZOMBIE;
|
||||
|
||||
p_mp = &mproc[rmp->mp_parent];
|
||||
pidarg = p_mp->mp_wpid; /* who's being waited for? */
|
||||
parent_waiting = p_mp->mp_flags & WAITING;
|
||||
right_child = /* child meets one of the 3 tests? */
|
||||
(pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp);
|
||||
|
||||
if (parent_waiting && right_child)
|
||||
tell_parent(rmp); /* tell parent */
|
||||
else
|
||||
sig_proc(p_mp, SIGCHLD); /* send parent a "child died" signal */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* tell_parent *
|
||||
*===========================================================================*/
|
||||
PUBLIC void tell_parent(child)
|
||||
PRIVATE void tell_parent(child)
|
||||
register struct mproc *child; /* tells which process is exiting */
|
||||
{
|
||||
int exitstatus, mp_parent;
|
||||
|
@ -405,9 +467,9 @@ register struct mproc *child; /* tells which process is exiting */
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* real_cleanup *
|
||||
* cleanup *
|
||||
*===========================================================================*/
|
||||
PUBLIC void real_cleanup(rmp)
|
||||
PRIVATE void cleanup(rmp)
|
||||
register struct mproc *rmp; /* tells which process is exiting */
|
||||
{
|
||||
/* Release the process table entry and reinitialize some field. */
|
||||
|
|
|
@ -596,34 +596,7 @@ message *m_ptr;
|
|||
/* Call is finished */
|
||||
rmp->mp_fs_call= PM_IDLE;
|
||||
|
||||
if (!(rmp->mp_flags & PRIV_PROC))
|
||||
{
|
||||
/* destroy the (user) process */
|
||||
if((r=sys_exit(proc_e)) != OK)
|
||||
{
|
||||
panic(__FILE__,
|
||||
"PM_EXIT_REPLY: sys_exit failed", r);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the memory occupied by the child. */
|
||||
if((s=vm_exit(rmp->mp_endpoint)) != OK) {
|
||||
panic(__FILE__, "vm_exit() failed", s);
|
||||
}
|
||||
|
||||
if (m_ptr->m_type == PM_EXIT_REPLY_TR &&
|
||||
rmp->mp_parent != INIT_PROC_NR)
|
||||
{
|
||||
/* Wake up the parent */
|
||||
mproc[rmp->mp_parent].mp_reply.reply_trace = 0;
|
||||
setreply(rmp->mp_parent, OK);
|
||||
}
|
||||
|
||||
/* Clean up if the parent has collected the exit
|
||||
* status
|
||||
*/
|
||||
if (rmp->mp_flags & TOLD_PARENT)
|
||||
real_cleanup(rmp);
|
||||
exit_restart(rmp, m_ptr->m_type);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -675,10 +648,6 @@ message *m_ptr;
|
|||
|
||||
case PM_CORE_REPLY:
|
||||
{
|
||||
int parent_waiting, right_child;
|
||||
pid_t pidarg;
|
||||
struct mproc *p_mp;
|
||||
|
||||
proc_e= m_ptr->PM_CORE_PROC;
|
||||
if (pm_isokendpt(proc_e, &proc_n) != OK)
|
||||
{
|
||||
|
@ -694,43 +663,7 @@ message *m_ptr;
|
|||
/* Call is finished */
|
||||
rmp->mp_fs_call= PM_IDLE;
|
||||
|
||||
p_mp = &mproc[rmp->mp_parent]; /* process' parent */
|
||||
pidarg = p_mp->mp_wpid; /* who's being waited for? */
|
||||
parent_waiting = p_mp->mp_flags & WAITING;
|
||||
right_child = /* child meets one of the 3 tests? */
|
||||
(pidarg == -1 || pidarg == rmp->mp_pid ||
|
||||
-pidarg == rmp->mp_procgrp);
|
||||
|
||||
if (parent_waiting && right_child) {
|
||||
tell_parent(rmp); /* tell parent */
|
||||
} else {
|
||||
/* parent not waiting, zombify child */
|
||||
rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
|
||||
rmp->mp_flags |= ZOMBIE;
|
||||
/* send parent a "child died" signal */
|
||||
sig_proc(p_mp, SIGCHLD);
|
||||
}
|
||||
|
||||
if (!(rmp->mp_flags & PRIV_PROC))
|
||||
{
|
||||
/* destroy the (user) process */
|
||||
if((r=sys_exit(proc_e)) != OK)
|
||||
{
|
||||
panic(__FILE__,
|
||||
"PM_CORE_REPLY: sys_exit failed", r);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the memory occupied by the child. */
|
||||
if((s=vm_exit(rmp->mp_endpoint)) != OK) {
|
||||
panic(__FILE__, "vm_exit() failed", s);
|
||||
}
|
||||
|
||||
/* Clean up if the parent has collected the exit
|
||||
* status
|
||||
*/
|
||||
if (rmp->mp_flags & TOLD_PARENT)
|
||||
real_cleanup(rmp);
|
||||
exit_restart(rmp, m_ptr->m_type);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,11 @@ _PROTOTYPE( void exec_restart, (struct mproc *rmp, int result) );
|
|||
/* forkexit.c */
|
||||
_PROTOTYPE( int do_fork, (void) );
|
||||
_PROTOTYPE( int do_fork_nb, (void) );
|
||||
_PROTOTYPE( int do_pm_exit, (void) );
|
||||
_PROTOTYPE( int do_exit, (void) );
|
||||
_PROTOTYPE( int do_waitpid, (void) );
|
||||
_PROTOTYPE( void pm_exit, (struct mproc *rmp, int exit_status,
|
||||
int for_trace) );
|
||||
_PROTOTYPE (void tell_parent, (struct mproc *child) );
|
||||
_PROTOTYPE( void real_cleanup, (struct mproc *rmp) );
|
||||
_PROTOTYPE( void exit_proc, (struct mproc *rmp, int exit_status,
|
||||
int exit_type) );
|
||||
_PROTOTYPE( void exit_restart, (struct mproc *rmp, int reply_type) );
|
||||
|
||||
/* getset.c */
|
||||
_PROTOTYPE( int do_getset, (void) );
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "mproc.h"
|
||||
#include "param.h"
|
||||
|
||||
FORWARD _PROTOTYPE( int dump_core, (struct mproc *rmp) );
|
||||
FORWARD _PROTOTYPE( void unpause, (int pro, int for_trace) );
|
||||
FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map) );
|
||||
FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp) );
|
||||
|
@ -422,6 +421,7 @@ int signo; /* signal to send to process (1 to _NSIG) */
|
|||
int s;
|
||||
int slot;
|
||||
int sigflags;
|
||||
int exit_type;
|
||||
|
||||
slot = (int) (rmp - mproc);
|
||||
if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
|
||||
|
@ -520,16 +520,13 @@ doterminate:
|
|||
}
|
||||
|
||||
rmp->mp_sigstatus = (char) signo;
|
||||
exit_type = PM_EXIT;
|
||||
if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) {
|
||||
printf("PM: signal %d for %d / %s\n", signo, rmp->mp_pid, rmp->mp_name);
|
||||
s= dump_core(rmp);
|
||||
if (s == SUSPEND) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not dumping core, just call exit */
|
||||
printf("PM: coredump signal %d for %d / %s\n", signo, rmp->mp_pid,
|
||||
rmp->mp_name);
|
||||
exit_type = PM_DUMPCORE;
|
||||
}
|
||||
pm_exit(rmp, 0, FALSE /*!for_trace*/); /* terminate process */
|
||||
exit_proc(rmp, 0, exit_type); /* terminate process */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -669,124 +666,3 @@ int for_trace; /* for tracing */
|
|||
r= notify(FS_PROC_NR);
|
||||
if (r != OK) panic("pm", "unpause: unable to notify FS", r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dump_core *
|
||||
*===========================================================================*/
|
||||
PRIVATE int dump_core(rmp)
|
||||
register struct mproc *rmp; /* whose core is to be dumped */
|
||||
{
|
||||
/* Make a core dump on the file "core", if possible. */
|
||||
|
||||
int r, proc_nr, proc_nr_e, parent_waiting;
|
||||
pid_t procgrp;
|
||||
#if 0
|
||||
vir_bytes current_sp;
|
||||
#endif
|
||||
struct mproc *p_mp;
|
||||
clock_t user_time, sys_time;
|
||||
|
||||
printf("dumpcore for %d / %s\n", rmp->mp_pid, rmp->mp_name);
|
||||
|
||||
/* Do not create core files for set uid execution */
|
||||
if (rmp->mp_realuid != rmp->mp_effuid) return OK;
|
||||
|
||||
/* Make sure the stack segment is up to date.
|
||||
* We don't want adjust() to fail unless current_sp is preposterous,
|
||||
* but it might fail due to safety checking. Also, we don't really want
|
||||
* the adjust() for sending a signal to fail due to safety checking.
|
||||
* Maybe make SAFETY_BYTES a parameter.
|
||||
*/
|
||||
#if 0
|
||||
if ((r= get_stack_ptr(rmp->mp_endpoint, ¤t_sp)) != OK)
|
||||
panic(__FILE__,"couldn't get new stack pointer (for core)", r);
|
||||
adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
|
||||
#endif
|
||||
|
||||
/* Tell FS about the exiting process. */
|
||||
if (rmp->mp_fs_call != PM_IDLE)
|
||||
panic(__FILE__, "dump_core: not idle", rmp->mp_fs_call);
|
||||
rmp->mp_fs_call= PM_DUMPCORE;
|
||||
r= notify(FS_PROC_NR);
|
||||
if (r != OK) panic(__FILE__, "dump_core: unable to notify FS", r);
|
||||
|
||||
/* Also perform most of the normal exit processing. Informing the parent
|
||||
* has to wait until we know whether the coredump was successful or not.
|
||||
*/
|
||||
|
||||
proc_nr = (int) (rmp - mproc); /* get process slot number */
|
||||
proc_nr_e = rmp->mp_endpoint;
|
||||
|
||||
/* Remember a session leader's process group. */
|
||||
procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
|
||||
|
||||
/* If the exited process has a timer pending, kill it. */
|
||||
if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr_e, (unsigned) 0);
|
||||
|
||||
/* Do accounting: fetch usage times and accumulate at parent. */
|
||||
if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)
|
||||
panic(__FILE__,"dump_core: sys_times failed", r);
|
||||
|
||||
p_mp = &mproc[rmp->mp_parent]; /* process' parent */
|
||||
p_mp->mp_child_utime += user_time + rmp->mp_child_utime; /* add user time */
|
||||
p_mp->mp_child_stime += sys_time + rmp->mp_child_stime; /* add system time */
|
||||
|
||||
/* Tell the kernel the process is no longer runnable to prevent it from
|
||||
* being scheduled in between the following steps. Then tell FS that it
|
||||
* the process has exited and finally, clean up the process at the kernel.
|
||||
* This order is important so that FS can tell drivers to cancel requests
|
||||
* such as copying to/ from the exiting process, before it is gone.
|
||||
*/
|
||||
sys_nice(proc_nr_e, PRIO_STOP); /* stop the process */
|
||||
if((r=vm_willexit(proc_nr_e)) != OK) {
|
||||
panic(__FILE__,"dump_core: vm_willexit failed", r);
|
||||
}
|
||||
|
||||
if(proc_nr_e != FS_PROC_NR) /* if it is not FS that is exiting.. */
|
||||
{
|
||||
if (rmp->mp_flags & PRIV_PROC)
|
||||
{
|
||||
/* destroy system processes without waiting for FS */
|
||||
if((r= sys_exit(rmp->mp_endpoint)) != OK)
|
||||
panic(__FILE__, "dump_core: sys_exit failed", r);
|
||||
|
||||
/* Just send a SIGCHLD. Dealing with waidpid is too complicated
|
||||
* here.
|
||||
*/
|
||||
p_mp = &mproc[rmp->mp_parent]; /* process' parent */
|
||||
sig_proc(p_mp, SIGCHLD);
|
||||
|
||||
/* Zombify to avoid calling sys_endksig */
|
||||
rmp->mp_flags |= ZOMBIE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("PM: FS died\n");
|
||||
return SUSPEND;
|
||||
}
|
||||
|
||||
/* Pending reply messages for the dead process cannot be delivered. */
|
||||
rmp->mp_flags &= ~REPLY;
|
||||
|
||||
/* Keep the process around until FS is finished with it. */
|
||||
|
||||
/* If the process has children, disinherit them. INIT is the new parent. */
|
||||
for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
|
||||
if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
|
||||
/* '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))
|
||||
{
|
||||
tell_parent(rmp);
|
||||
real_cleanup(rmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a hangup to the process' process group if it was a session leader. */
|
||||
if (procgrp != 0) check_sig(-procgrp, SIGHUP);
|
||||
|
||||
return SUSPEND;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ char core_name[] = "core"; /* file name where core images are produced */
|
|||
|
||||
_PROTOTYPE (int (*call_vec[]), (void) ) = {
|
||||
no_sys, /* 0 = unused */
|
||||
do_pm_exit, /* 1 = exit */
|
||||
do_exit, /* 1 = exit */
|
||||
do_fork, /* 2 = fork */
|
||||
no_sys, /* 3 = read */
|
||||
no_sys, /* 4 = write */
|
||||
|
|
|
@ -112,7 +112,7 @@ PUBLIC int do_trace()
|
|||
|
||||
switch (m_in.request) {
|
||||
case T_EXIT: /* exit */
|
||||
pm_exit(child, (int) m_in.data, TRUE /*for_trace*/);
|
||||
exit_proc(child, (int) m_in.data, PM_EXIT_TR);
|
||||
/* Do not reply to the caller until FS has processed the exit
|
||||
* request.
|
||||
*/
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
* The entry points are:
|
||||
* find_param: look up a boot monitor parameter
|
||||
* get_free_pid: get a free process or group id
|
||||
* allowed: see if an access is permitted
|
||||
* no_sys: called for invalid system call numbers
|
||||
* panic: PM has run aground of a fatal error
|
||||
* get_stack_ptr: get stack pointer of given process
|
||||
* proc_from_pid: return process pointer from pid number
|
||||
* pm_isokendpt: check the validity of an endpoint
|
||||
*/
|
||||
|
||||
#include "pm.h"
|
||||
|
|
Loading…
Reference in a new issue