Allow a process to kill itself. Remove the endpoint of a process that kills

itself before reporting the singal to pm.
This commit is contained in:
Philip Homburg 2006-03-15 12:01:59 +00:00
parent b351811f18
commit c1da6e6e24
6 changed files with 100 additions and 56 deletions

View file

@ -42,6 +42,7 @@
#include "debug.h"
#include "kernel.h"
#include "proc.h"
#include <signal.h>
/* Scheduling and message passing functions. The functions are available to
* other parts of the kernel through lock_...(). The lock temporarily disables
@ -147,7 +148,7 @@ long bit_map; /* notification event set or flags */
* anywhere in data or stack or gap. It will have to be made more elaborate
* for machines which don't have the gap mapped.
*/
if (function & CHECK_PTR) {
if (function & CHECK_PTR) {
vlo = (vir_bytes) m_ptr >> CLICK_SHIFT;
vhi = ((vir_bytes) m_ptr + MESS_SIZE - 1) >> CLICK_SHIFT;
if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
@ -164,7 +165,7 @@ long bit_map; /* notification event set or flags */
/* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY,
* verify that the caller is allowed to send to the given destination.
*/
if (function & CHECK_DST) {
if (function & CHECK_DST) {
if (! get_sys_bit(priv(caller_ptr)->s_ipc_to, nr_to_id(src_dst))) {
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("sys_call: ipc mask denied trap %d from %d to %d\n",
@ -295,6 +296,8 @@ unsigned flags; /* system call flags */
dst_p = _ENDPOINT_P(dst_e);
dst_ptr = proc_addr(dst_p);
if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED;
/* Check if 'dst' is blocked waiting for this message. The destination's
* SENDING flag may be set when its SENDREC call blocked while sending.
*/
@ -345,7 +348,12 @@ unsigned flags; /* system call flags */
int i, src_id, src_proc_nr, src_p;
if(src_e == ANY) src_p = ANY;
else okendpt(src_e, &src_p);
else
{
okendpt(src_e, &src_p);
if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED;
}
/* Check to see if a message from desired source is already available.
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is

View file

@ -69,6 +69,7 @@ struct proc {
#define P_STOP 0x40 /* set when process is being traced */
#define NO_PRIV 0x80 /* keep forked system process from running */
#define NO_PRIORITY 0x100 /* process has been stopped */
#define NO_ENDPOINT 0x200 /* process cannot send or receive messages */
/* Misc flags */
#define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */

View file

@ -59,6 +59,7 @@ _PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( void clear_endpoint, (struct proc *rc) );
#if (CHIP == INTEL)

View file

@ -19,6 +19,7 @@
* umap_bios: map virtual address in BIOS_SEG to physical
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
* clear_endpoint: remove a process' ability to send and receive messages
*
* Changes:
* Aug 04, 2005 check if system call is allowed (Jorrit N. Herder)
@ -471,3 +472,76 @@ vir_bytes bytes; /* # of bytes to copy */
return(OK);
}
/*===========================================================================*
* clear_endpoint *
*===========================================================================*/
PUBLIC void clear_endpoint(rc)
register struct proc *rc; /* slot of process to clean up */
{
register struct proc *rp; /* iterate over process table */
register struct proc **xpp; /* iterate over caller queue */
int i;
int sys_id;
if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
/* Make sure that the exiting process is no longer scheduled. */
if (rc->p_rts_flags == 0) lock_dequeue(rc);
rc->p_rts_flags |= NO_ENDPOINT;
/* If the process happens to be queued trying to send a
* message, then it must be removed from the message queues.
*/
if (rc->p_rts_flags & SENDING) {
int target_proc;
okendpt(rc->p_sendto_e, &target_proc);
xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
while (*xpp != NIL_PROC) { /* check entire queue */
if (*xpp == rc) { /* process is on the queue */
*xpp = (*xpp)->p_q_link; /* replace by next process */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d removed from queue at %d\n",
proc_nr(rc), rc->p_sendto_e);
#endif
break; /* can only be queued once */
}
xpp = &(*xpp)->p_q_link; /* proceed to next queued */
}
rc->p_rts_flags &= ~SENDING;
}
rc->p_rts_flags &= ~RECEIVING;
/* Likewise, if another process was sending or receive a message to or from
* the exiting process, it must be alerted that process no longer is alive.
* Check all processes.
*/
for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
if(isemptyp(rp))
continue;
/* Unset pending notification bits. */
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
/* Check if process is receiving from exiting process. */
if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
rp->p_reg.retreg = ESRCDIED; /* report source died */
rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
#endif
if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
rp->p_reg.retreg = EDSTDIED; /* report destination died */
rp->p_rts_flags &= ~SENDING; /* no longer sending */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
#endif
if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
}
}

View file

@ -57,6 +57,9 @@ register struct proc *rc; /* slot of process to clean up */
/* Don't clear if already cleared. */
if(isemptyp(rc)) return;
/* Remove the process' ability to send and receive messages */
clear_endpoint(rc);
/* Turn off any alarm timers at the clock. */
reset_timer(&priv(rc)->s_alarm_timer);
@ -81,57 +84,6 @@ register struct proc *rc; /* slot of process to clean up */
rc->p_rts_flags = SLOT_FREE;
if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
/* If the process being terminated happens to be queued trying to send a
* message (e.g., the process was killed by a signal, rather than it doing
* a normal exit), then it must be removed from the message queues.
*/
if (saved_rts_flags & SENDING) {
int target_proc;
okendpt(rc->p_sendto_e, &target_proc);
xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
while (*xpp != NIL_PROC) { /* check entire queue */
if (*xpp == rc) { /* process is on the queue */
*xpp = (*xpp)->p_q_link; /* replace by next process */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d removed from queue at %d\n",
proc_nr(rc), rc->p_sendto_e);
#endif
break; /* can only be queued once */
}
xpp = &(*xpp)->p_q_link; /* proceed to next queued */
}
}
/* Likewise, if another process was sending or receive a message to or from
* the exiting process, it must be alerted that process no longer is alive.
* Check all processes.
*/
for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
if(isemptyp(rp))
continue;
/* Unset pending notification bits. */
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
/* Check if process is receiving from exiting process. */
if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
rp->p_reg.retreg = ESRCDIED; /* report source died */
rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
#endif
if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
rp->p_reg.retreg = EDSTDIED; /* report destination died */
rp->p_rts_flags &= ~SENDING; /* no longer sending */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
#endif
if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
}
/* Clean up virtual memory */
if (rc->p_misc_flags & MF_VM)
vm_map_default(rc);

View file

@ -26,15 +26,23 @@ message *m_ptr; /* pointer to request message */
* are usually blocked on a RECEIVE), they can request the PM to transform
* signals into messages. This is done by the PM with a call to sys_kill().
*/
proc_nr_t proc_nr;
proc_nr_t proc_nr, proc_nr_e;
int sig_nr = m_ptr->SIG_NUMBER;
if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
proc_nr_e= m_ptr->SIG_ENDPT;
if (proc_nr_e == SELF)
proc_nr_e= m_ptr->m_source;
if (!isokendpt(proc_nr_e, &proc_nr)) return(EINVAL);
if (sig_nr > _NSIG) return(EINVAL);
if (iskerneln(proc_nr)) return(EPERM);
/* Set pending signal to be processed by the PM. */
cause_sig(proc_nr, sig_nr);
if (sig_nr == SIGKILL)
clear_endpoint(proc_addr(proc_nr));
return(OK);
}