#define PM_CORE_PROC m1_i1
#define PM_CORE_SEGPTR m1_p1
#define PM_UNPAUSE_TR (PM_BASE + 15) /* interrupted process (for tracing) */
-#define PM_EXIT_TR (PM_BASE + 16) /* Tell FS about the exiting process
- * (for tracing)
- */
/* Replies */
#define PM_EXIT_REPLY (PM_BASE + 20) /* Reply from FS */
#define PM_CORE_REPLY (PM_BASE + 23) /* Reply from FS */
/* PM_CORE_PROC m1_i1 */
#define PM_CORE_STATUS m1_i2 /* OK or failure */
-#define PM_EXIT_REPLY_TR (PM_BASE + 24) /* Reply from FS */
/* Parameters for the EXEC_NEWMEM call */
#define EXC_NM_PROC m1_i1 /* process that needs new map */
/* Use SIGILL signal that something went wrong */
rmp->mp_sigstatus = SIGILL;
- exit_proc(rmp, 0, PM_EXIT);
+ exit_proc(rmp, 0, FALSE /*dump_core*/);
return;
}
setreply(rmp-mproc, result);
/* 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.
*/
- exit_proc(mp, m_in.status, PM_EXIT);
+ exit_proc(mp, m_in.status, FALSE /*dump_core*/);
return(SUSPEND); /* can't communicate from beyond the grave */
}
/*===========================================================================*
* exit_proc *
*===========================================================================*/
-PUBLIC void exit_proc(rmp, exit_status, exit_type)
+PUBLIC void exit_proc(rmp, exit_status, dump_core)
register struct mproc *rmp; /* pointer to the process to be terminated */
int exit_status; /* the process' exit status (for parent) */
-int exit_type; /* one of PM_EXIT, PM_EXIT_TR, PM_DUMPCORE */
+int dump_core; /* flag indicating whether to dump core */
{
/* A process is done. Release most of the process' possessions. If its
* parent is waiting, release the rest, else keep the process slot and
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;
+ if (dump_core && rmp->mp_realuid != rmp->mp_effuid)
+ dump_core = FALSE;
/* 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;
+ if (dump_core && (rmp->mp_flags & PRIV_PROC))
+ dump_core = FALSE;
proc_nr = (int) (rmp - mproc); /* get process slot number */
proc_nr_e = rmp->mp_endpoint;
/* Tell FS about the exiting process. */
if (rmp->mp_fs_call != PM_IDLE)
panic(__FILE__, "exit_proc: not idle", rmp->mp_fs_call);
- rmp->mp_fs_call= exit_type;
+ rmp->mp_fs_call= dump_core ? PM_DUMPCORE : PM_EXIT;
r= notify(FS_PROC_NR);
if (r != OK) panic(__FILE__, "exit_proc: unable to notify FS", r);
/* 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)
+ if (!dump_core)
zombify(rmp);
/* If the process has children, disinherit them. INIT is the new parent. */
/*===========================================================================*
* exit_restart *
*===========================================================================*/
-PUBLIC void exit_restart(rmp, reply_type)
+PUBLIC void exit_restart(rmp, dump_core)
struct mproc *rmp; /* pointer to the process being terminated */
-int reply_type; /* one of PM_EXIT_REPLY(_TR), PM_CORE_REPLY */
+int dump_core; /* flag indicating whether to dump core */
{
/* 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)
+ if (dump_core)
zombify(rmp);
if (!(rmp->mp_flags & PRIV_PROC))
panic(__FILE__, "exit_restart: vm_exit failed", r);
}
- if (reply_type == PM_EXIT_REPLY_TR && rmp->mp_parent != INIT_PROC_NR)
+ if ((rmp->mp_flags & TRACE_EXIT) && 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;
if (rmp->mp_flags & ZOMBIE)
panic(__FILE__, "zombify: process was already a zombie", NO_NUM);
- rmp->mp_flags &= (IN_USE|PRIV_PROC|EXITING);
+ rmp->mp_flags &= (IN_USE|PRIV_PROC|EXITING|TRACE_EXIT);
rmp->mp_flags |= ZOMBIE;
p_mp = &mproc[rmp->mp_parent];
FORWARD _PROTOTYPE( int get_nice_value, (int queue) );
FORWARD _PROTOTYPE( void send_work, (void) );
FORWARD _PROTOTYPE( void handle_fs_reply, (message *m_ptr) );
+FORWARD _PROTOTYPE( void restart_sigs, (struct mproc *rmp) );
#define click_to_round_k(n) \
((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
case PM_REBOOT_REPLY:
case PM_EXEC_REPLY:
case PM_CORE_REPLY:
- case PM_EXIT_REPLY_TR:
if (who_e == FS_PROC_NR)
{
handle_fs_reply(&m_in);
}
}
-/*=========================================================================*
- * send_work *
- *=========================================================================*/
+/*===========================================================================*
+ * send_work *
+ *===========================================================================*/
PRIVATE void send_work()
{
int r, call;
}
case PM_EXIT:
- case PM_EXIT_TR:
m.m_type= call;
m.PM_EXIT_PROC= rmp->mp_endpoint;
}
if (m.m_type != PM_IDLE)
{
- if (rmp->mp_fs_call == PM_IDLE &&
- rmp->mp_fs_call2 == PM_IDLE &&
- (rmp->mp_flags & PM_SIG_PENDING))
- {
- rmp->mp_flags &= ~PM_SIG_PENDING;
- check_pending(rmp);
- if (!(rmp->mp_flags & PM_SIG_PENDING))
- {
- /* Allow the process to be scheduled */
- sys_nice(rmp->mp_endpoint, rmp->mp_nice);
- }
- }
+ restart_sigs(rmp);
}
else if (report_reboot)
{
if (r != OK) panic("pm", "send_work: send failed", r);
}
+/*===========================================================================*
+ * handle_fs_reply *
+ *===========================================================================*/
PRIVATE void handle_fs_reply(m_ptr)
message *m_ptr;
{
switch(m_ptr->m_type)
{
case PM_EXIT_REPLY:
- case PM_EXIT_REPLY_TR:
proc_e= m_ptr->PM_EXIT_PROC;
if (pm_isokendpt(proc_e, &proc_n) != OK)
{
/* Call is finished */
rmp->mp_fs_call= PM_IDLE;
- exit_restart(rmp, m_ptr->m_type);
+ exit_restart(rmp, FALSE /*dump_core*/);
break;
exec_restart(rmp, m_ptr->PM_EXEC_STATUS);
- if (rmp->mp_flags & PM_SIG_PENDING)
- {
- printf("handle_fs_reply: restarting signals\n");
- rmp->mp_flags &= ~PM_SIG_PENDING;
- check_pending(rmp);
- if (!(rmp->mp_flags & PM_SIG_PENDING))
- {
- printf("handle_fs_reply: calling sys_nice\n");
- /* Allow the process to be scheduled */
- sys_nice(rmp->mp_endpoint, rmp->mp_nice);
- }
- else
- printf("handle_fs_reply: more signals\n");
- }
+ restart_sigs(rmp);
+
break;
case PM_CORE_REPLY:
/* Call is finished */
rmp->mp_fs_call= PM_IDLE;
- exit_restart(rmp, m_ptr->m_type);
+ exit_restart(rmp, TRUE /*dump_core*/);
break;
}
}
+/*===========================================================================*
+ * restart_sigs *
+ *===========================================================================*/
+PRIVATE void restart_sigs(rmp)
+struct mproc *rmp;
+{
+
+ if (rmp->mp_fs_call != PM_IDLE || rmp->mp_fs_call2 != PM_IDLE)
+ return;
+
+ if (rmp->mp_flags & TRACE_EXIT) {
+ exit_proc(rmp, rmp->mp_exitstatus, FALSE /*dump_core*/);
+ }
+ else if (rmp->mp_flags & PM_SIG_PENDING) {
+ rmp->mp_flags &= ~PM_SIG_PENDING;
+ check_pending(rmp);
+ if (!(rmp->mp_flags & PM_SIG_PENDING)) {
+ /* Allow the process to be scheduled */
+ sys_nice(rmp->mp_endpoint, rmp->mp_nice);
+ }
+ }
+}
#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 TRACE_EXIT 0x40000 /* tracer is forcing this process to exit */
#define NIL_MPROC ((struct mproc *) 0)
_PROTOTYPE( int do_exit, (void) );
_PROTOTYPE( int do_waitpid, (void) );
_PROTOTYPE( void exit_proc, (struct mproc *rmp, int exit_status,
- int exit_type) );
-_PROTOTYPE( void exit_restart, (struct mproc *rmp, int reply_type) );
+ int dump_core) );
+_PROTOTYPE( void exit_restart, (struct mproc *rmp, int dump_core) );
/* getset.c */
_PROTOTYPE( int do_getset, (void) );
int s;
int slot;
int sigflags;
- int exit_type;
slot = (int) (rmp - mproc);
if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
return;
}
+ /* Terminate process */
rmp->mp_sigstatus = (char) signo;
- exit_type = PM_EXIT;
if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) {
printf("PM: coredump signal %d for %d / %s\n", signo, rmp->mp_pid,
rmp->mp_name);
- exit_type = PM_DUMPCORE;
+ exit_proc(rmp, 0, TRUE /*dump_core*/);
+ }
+ else {
+ exit_proc(rmp, 0, FALSE /*dump_core*/);
}
- exit_proc(rmp, 0, exit_type); /* terminate process */
}
/*===========================================================================*
switch (m_in.request) {
case T_EXIT: /* exit */
- exit_proc(child, (int) m_in.data, PM_EXIT_TR);
+ child->mp_flags |= TRACE_EXIT;
+
+ /* Defer the exit if the traced process has an FS call pending. */
+ if (child->mp_fs_call != PM_IDLE || child->mp_fs_call2 != PM_IDLE)
+ child->mp_exitstatus = (int) m_in.data; /* save for later */
+ else
+ exit_proc(child, (int) m_in.data, FALSE /*dump_core*/);
+
/* Do not reply to the caller until FS has processed the exit
* request.
*/
break;
case PM_EXIT:
- case PM_EXIT_TR:
pm_exit(m.PM_EXIT_PROC);
/* Reply dummy status to PM for synchronization */
- m.m_type= (call == PM_EXIT_TR ? PM_EXIT_REPLY_TR :
- PM_EXIT_REPLY);
+ m.m_type= PM_EXIT_REPLY;
/* Keep m.PM_EXIT_PROC */
r= send(PM_PROC_NR, &m);