]> Zhao Yanbai Git Server - minix.git/commitdiff
Allow a process to kill itself. Remove the endpoint of a process that kills
authorPhilip Homburg <philip@cs.vu.nl>
Wed, 15 Mar 2006 12:01:59 +0000 (12:01 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Wed, 15 Mar 2006 12:01:59 +0000 (12:01 +0000)
itself before reporting the singal to pm.

kernel/proc.c
kernel/proc.h
kernel/proto.h
kernel/system.c
kernel/system/do_exit.c
kernel/system/do_kill.c

index 2635d299daef1a0bb8aeff2267d213d02d663cdd..138126e03ac4f7258941e82e1aa9c5fa855ea440 100755 (executable)
@@ -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
index df4462413ab467eda92e791c80528b1f2b422174..ec51bacbba0b180b00e6705804e0228ead1094dc 100755 (executable)
@@ -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 */
index 071364ba66d364bb5e5fd698172549b6db468843..91387954aab274875e04f754e0270d7a22c26cb1 100755 (executable)
@@ -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)
 
index ba949ee334db5f50404d92c2a7054217f680e811..5c964ea89b586647ade88afb3a4c8e4fdcb07217 100755 (executable)
@@ -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 */
+      } 
+  }
+}
+
+
index 670a071089093048002446cadacf52837cc7596a..165ea855cd33d602196b1fb372e7f6664ac32c71 100644 (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);
index eab947d7d0747a4da8e584633e93f4bb3d322c41..289bcc099a145eee62664506e0848c982699fc66 100644 (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);
 }