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 */ | 			/* Use SIGILL signal that something went wrong */ | ||||||
| 			rmp->mp_sigstatus = SIGILL; | 			rmp->mp_sigstatus = SIGILL; | ||||||
| 			pm_exit(rmp, 0, FALSE /*!for_trace*/); | 			exit_proc(rmp, 0, PM_EXIT); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		setreply(rmp-mproc, result); | 		setreply(rmp-mproc, result); | ||||||
|  | |||||||
| @ -7,11 +7,12 @@ | |||||||
|  * exits first, it continues to occupy a slot until the parent does a WAIT. |  * exits first, it continues to occupy a slot until the parent does a WAIT. | ||||||
|  * |  * | ||||||
|  * The entry points into this file are: |  * The entry points into this file are: | ||||||
|  *   do_fork:	 perform the FORK system call |  *   do_fork:		perform the FORK system call | ||||||
|  *   do_pm_exit: perform the EXIT system call (by calling pm_exit()) |  *   do_fork_nb:	special nonblocking version of FORK, for RS | ||||||
|  *   pm_exit:	 actually do the exiting |  *   do_exit:		perform the EXIT system call (by calling exit_proc()) | ||||||
|  *   do_wait:	 perform the WAITPID or WAIT system call |  *   exit_proc:		actually do the exiting, and tell FS about it | ||||||
|  *   tell_parent: tell parent about the death of a child |  *   exit_restart:	continue exiting a process after FS has replied | ||||||
|  |  *   do_waitpid:	perform the WAITPID or WAIT system call | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "pm.h" | #include "pm.h" | ||||||
| @ -26,7 +27,9 @@ | |||||||
| 
 | 
 | ||||||
| #define LAST_FEW            2	/* last few slots reserved for superuser */ | #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					     * |  *				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. |  * 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 */ |   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 */ | register struct mproc *rmp;	/* pointer to the process to be terminated */ | ||||||
| int exit_status;		/* the process' exit status (for parent) */ | 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
 | /* A process is done.  Release most of the process' possessions.  If its
 | ||||||
|  * parent is waiting, release the rest, else keep the process slot and |  * parent is waiting, release the rest, else keep the process slot and | ||||||
|  * become a zombie. |  * become a zombie. | ||||||
|  */ |  */ | ||||||
|   register int proc_nr, proc_nr_e; |   register int proc_nr, proc_nr_e; | ||||||
|   int parent_waiting, right_child, r; |   int parent_waiting, r; | ||||||
|   pid_t pidarg, procgrp; |   pid_t procgrp; | ||||||
|   struct mproc *p_mp; |   struct mproc *p_mp; | ||||||
|   clock_t user_time, sys_time; |   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 = (int) (rmp - mproc);	/* get process slot number */ | ||||||
|   proc_nr_e = rmp->mp_endpoint; |   proc_nr_e = rmp->mp_endpoint; | ||||||
| 
 | 
 | ||||||
| @ -213,7 +226,7 @@ int for_trace; | |||||||
| 
 | 
 | ||||||
|   /* Do accounting: fetch usage times and accumulate at parent. */ |   /* Do accounting: fetch usage times and accumulate at parent. */ | ||||||
|   if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK) |   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 = &mproc[rmp->mp_parent];			/* process' parent */ | ||||||
|   p_mp->mp_child_utime += user_time + rmp->mp_child_utime; /* add user time */ |   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 */ |   sys_nice(proc_nr_e, PRIO_STOP);	/* stop the process */ | ||||||
|   if((r=vm_willexit(proc_nr_e)) != OK) { |   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) |   if (proc_nr_e == INIT_PROC_NR) | ||||||
| @ -240,16 +253,16 @@ int for_trace; | |||||||
|   { |   { | ||||||
| 	/* Tell FS about the exiting process. */ | 	/* Tell FS about the exiting process. */ | ||||||
| 	if (rmp->mp_fs_call != PM_IDLE) | 	if (rmp->mp_fs_call != PM_IDLE) | ||||||
| 		panic(__FILE__, "pm_exit: not idle", rmp->mp_fs_call); | 		panic(__FILE__, "exit_proc: not idle", rmp->mp_fs_call); | ||||||
| 	rmp->mp_fs_call= (for_trace ? PM_EXIT_TR : PM_EXIT); | 	rmp->mp_fs_call= exit_type; | ||||||
| 	r= notify(FS_PROC_NR); | 	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) | 	if (rmp->mp_flags & PRIV_PROC) | ||||||
| 	{ | 	{ | ||||||
| 		/* destroy system processes without waiting for FS */ | 		/* destroy system processes without waiting for FS */ | ||||||
| 		if((r= sys_exit(rmp->mp_endpoint)) != OK) | 		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 |   else | ||||||
| @ -264,18 +277,12 @@ int for_trace; | |||||||
|   /* Keep the process around until FS is finished with it. */ |   /* Keep the process around until FS is finished with it. */ | ||||||
|    |    | ||||||
|   rmp->mp_exitstatus = (char) exit_status; |   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) { |   /* For normal exits, try to notify the parent as soon as possible.
 | ||||||
| 	tell_parent(rmp);		/* tell parent */ |    * For core dumps, notify the parent only once the core dump has been made. | ||||||
|   } else { |    */ | ||||||
| 	rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA); |   if (exit_type != PM_DUMPCORE) | ||||||
| 	rmp->mp_flags |= ZOMBIE;	/* parent not waiting, zombify child */ | 	zombify(rmp); | ||||||
| 	sig_proc(p_mp, SIGCHLD);	/* send parent a "child died" signal */ |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   /* If the process has children, disinherit them.  INIT is the new parent. */ |   /* If the process has children, disinherit them.  INIT is the new parent. */ | ||||||
|   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) { |   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) { | ||||||
| @ -284,9 +291,11 @@ int for_trace; | |||||||
| 		rmp->mp_parent = INIT_PROC_NR; | 		rmp->mp_parent = INIT_PROC_NR; | ||||||
| 		parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING; | 		parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING; | ||||||
| 		if (parent_waiting && (rmp->mp_flags & ZOMBIE) && | 		if (parent_waiting && (rmp->mp_flags & ZOMBIE) && | ||||||
| 			!(rmp->mp_flags & TOLD_PARENT) && | 			!(rmp->mp_flags & TOLD_PARENT)) { | ||||||
| 			rmp->mp_fs_call != PM_EXIT) { | 			tell_parent(rmp); | ||||||
| 			cleanup(rmp); | 
 | ||||||
|  | 			if (rmp->mp_fs_call == PM_IDLE) | ||||||
|  | 				cleanup(rmp); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   } |   } | ||||||
| @ -295,6 +304,46 @@ int for_trace; | |||||||
|   if (procgrp != 0) check_sig(-procgrp, SIGHUP); |   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				     * |  *				do_waitpid				     * | ||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| @ -305,7 +354,7 @@ PUBLIC int do_waitpid() | |||||||
|  * really wait.  |  * really wait.  | ||||||
|  * A process calling WAIT never gets a reply in the usual way at the end |  * 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). |  * 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. |  * to awaken the caller. | ||||||
|  * Both WAIT and WAITPID are handled by this code. |  * 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. */ | 			/* This child meets the pid test and has exited. */ | ||||||
| 			tell_parent(rp); /* this child has already exited */ | 			tell_parent(rp); /* this child has already exited */ | ||||||
| 			if (rp->mp_fs_call == PM_IDLE) | 			if (rp->mp_fs_call == PM_IDLE) | ||||||
| 				real_cleanup(rp); | 				cleanup(rp); | ||||||
| 			return(SUSPEND); | 			return(SUSPEND); | ||||||
| 		} | 		} | ||||||
| 		if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) { | 		if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) { | ||||||
| @ -363,27 +412,40 @@ PUBLIC int do_waitpid() | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*===========================================================================*
 | /*===========================================================================*
 | ||||||
|  *				cleanup					     * |  *				zombify					     * | ||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| PRIVATE void cleanup(child) | PRIVATE void zombify(rmp) | ||||||
| register struct mproc *child;	/* tells which process is exiting */ | struct mproc *rmp; | ||||||
| { | { | ||||||
| /* Finish off the exit of a process.  The process has exited or been killed
 | /* Zombify a process. If the parent is waiting, notify it immediately.
 | ||||||
|  * by a signal, and its parent is waiting. |  * 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) |   if (rmp->mp_flags & ZOMBIE) | ||||||
| 	panic(__FILE__, "cleanup: not idle", child->mp_fs_call); | 	panic(__FILE__, "zombify: process was already a zombie", NO_NUM); | ||||||
| 
 | 
 | ||||||
|   tell_parent(child); |   rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA); | ||||||
|   real_cleanup(child); |   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				     * |  *				tell_parent				     * | ||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| PUBLIC void tell_parent(child) | PRIVATE void tell_parent(child) | ||||||
| register struct mproc *child;	/* tells which process is exiting */ | register struct mproc *child;	/* tells which process is exiting */ | ||||||
| { | { | ||||||
|   int exitstatus, mp_parent; |   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 */ | register struct mproc *rmp;	/* tells which process is exiting */ | ||||||
| { | { | ||||||
|   /* Release the process table entry and reinitialize some field. */ |   /* Release the process table entry and reinitialize some field. */ | ||||||
|  | |||||||
| @ -596,34 +596,7 @@ message *m_ptr; | |||||||
| 		/* Call is finished */ | 		/* Call is finished */ | ||||||
| 		rmp->mp_fs_call= PM_IDLE; | 		rmp->mp_fs_call= PM_IDLE; | ||||||
| 
 | 
 | ||||||
| 		if (!(rmp->mp_flags & PRIV_PROC)) | 		exit_restart(rmp, m_ptr->m_type); | ||||||
| 		{ |  | ||||||
| 			/* 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); |  | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| @ -675,10 +648,6 @@ message *m_ptr; | |||||||
| 
 | 
 | ||||||
| 	case PM_CORE_REPLY: | 	case PM_CORE_REPLY: | ||||||
| 	{ | 	{ | ||||||
| 		int parent_waiting, right_child; |  | ||||||
| 		pid_t pidarg; |  | ||||||
| 		struct mproc *p_mp; |  | ||||||
| 
 |  | ||||||
| 		proc_e= m_ptr->PM_CORE_PROC; | 		proc_e= m_ptr->PM_CORE_PROC; | ||||||
| 		if (pm_isokendpt(proc_e, &proc_n) != OK) | 		if (pm_isokendpt(proc_e, &proc_n) != OK) | ||||||
| 		{ | 		{ | ||||||
| @ -694,43 +663,7 @@ message *m_ptr; | |||||||
| 		/* Call is finished */ | 		/* Call is finished */ | ||||||
| 		rmp->mp_fs_call= PM_IDLE; | 		rmp->mp_fs_call= PM_IDLE; | ||||||
| 
 | 
 | ||||||
| 		p_mp = &mproc[rmp->mp_parent];		/* process' parent */ | 		exit_restart(rmp, m_ptr->m_type); | ||||||
| 		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); |  | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -33,12 +33,11 @@ _PROTOTYPE( void exec_restart, (struct mproc *rmp, int result)		); | |||||||
| /* forkexit.c */ | /* forkexit.c */ | ||||||
| _PROTOTYPE( int do_fork, (void)						); | _PROTOTYPE( int do_fork, (void)						); | ||||||
| _PROTOTYPE( int do_fork_nb, (void)					); | _PROTOTYPE( int do_fork_nb, (void)					); | ||||||
| _PROTOTYPE( int do_pm_exit, (void)					); | _PROTOTYPE( int do_exit, (void)						); | ||||||
| _PROTOTYPE( int do_waitpid, (void)					); | _PROTOTYPE( int do_waitpid, (void)					); | ||||||
| _PROTOTYPE( void pm_exit, (struct mproc *rmp, int exit_status, | _PROTOTYPE( void exit_proc, (struct mproc *rmp, int exit_status, | ||||||
| 	int for_trace)							); | 	int exit_type)							); | ||||||
| _PROTOTYPE (void tell_parent, (struct mproc *child)			); | _PROTOTYPE( void exit_restart, (struct mproc *rmp, int reply_type)	); | ||||||
| _PROTOTYPE( void real_cleanup, (struct mproc *rmp)			); |  | ||||||
| 
 | 
 | ||||||
| /* getset.c */ | /* getset.c */ | ||||||
| _PROTOTYPE( int do_getset, (void)					); | _PROTOTYPE( int do_getset, (void)					); | ||||||
|  | |||||||
| @ -34,7 +34,6 @@ | |||||||
| #include "mproc.h" | #include "mproc.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
| 
 | 
 | ||||||
| FORWARD _PROTOTYPE( int dump_core, (struct mproc *rmp)			); |  | ||||||
| FORWARD _PROTOTYPE( void unpause, (int pro, int for_trace)		); | FORWARD _PROTOTYPE( void unpause, (int pro, int for_trace)		); | ||||||
| FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map)	); | FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map)	); | ||||||
| FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp)		); | 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 s; | ||||||
|   int slot; |   int slot; | ||||||
|   int sigflags; |   int sigflags; | ||||||
|  |   int exit_type; | ||||||
| 
 | 
 | ||||||
|   slot = (int) (rmp - mproc); |   slot = (int) (rmp - mproc); | ||||||
|   if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) { |   if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) { | ||||||
| @ -520,16 +520,13 @@ doterminate: | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   rmp->mp_sigstatus = (char) signo; |   rmp->mp_sigstatus = (char) signo; | ||||||
|  |   exit_type = PM_EXIT; | ||||||
|   if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) { |   if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) { | ||||||
| 	printf("PM: signal %d for %d / %s\n", signo, rmp->mp_pid, rmp->mp_name); | 	printf("PM: coredump signal %d for %d / %s\n", signo, rmp->mp_pid, | ||||||
| 	s= dump_core(rmp); | 		rmp->mp_name); | ||||||
| 	if (s == SUSPEND) { | 	exit_type = PM_DUMPCORE; | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* Not dumping core, just call exit */ |  | ||||||
|   } |   } | ||||||
|   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); |   r= notify(FS_PROC_NR); | ||||||
|   if (r != OK) panic("pm", "unpause: unable to notify FS", r); |   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) ) = { | _PROTOTYPE (int (*call_vec[]), (void) ) = { | ||||||
| 	no_sys,		/*  0 = unused	*/ | 	no_sys,		/*  0 = unused	*/ | ||||||
| 	do_pm_exit,	/*  1 = exit	*/ | 	do_exit,	/*  1 = exit	*/ | ||||||
| 	do_fork,	/*  2 = fork	*/ | 	do_fork,	/*  2 = fork	*/ | ||||||
| 	no_sys,		/*  3 = read	*/ | 	no_sys,		/*  3 = read	*/ | ||||||
| 	no_sys,		/*  4 = write	*/ | 	no_sys,		/*  4 = write	*/ | ||||||
|  | |||||||
| @ -112,7 +112,7 @@ PUBLIC int do_trace() | |||||||
| 
 | 
 | ||||||
|   switch (m_in.request) { |   switch (m_in.request) { | ||||||
|   case T_EXIT:		/* exit */ |   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
 | 	/* Do not reply to the caller until FS has processed the exit
 | ||||||
| 	 * request. | 	 * request. | ||||||
| 	 */ | 	 */ | ||||||
|  | |||||||
| @ -3,11 +3,9 @@ | |||||||
|  * The entry points are: |  * The entry points are: | ||||||
|  *   find_param:	look up a boot monitor parameter |  *   find_param:	look up a boot monitor parameter | ||||||
|  *   get_free_pid:	get a free process or group id |  *   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 |  *   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 |  *   proc_from_pid:	return process pointer from pid number | ||||||
|  |  *   pm_isokendpt:	check the validity of an endpoint | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "pm.h" | #include "pm.h" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 David van Moolenbroek
						David van Moolenbroek