. service tells you which device it couldn't stat
[minix3.git] / servers / pm / signal.c
blob26d1bcef5063626e96488b8d3cadf5c9ef121b45
1 /* This file handles signals, which are asynchronous events and are generally
2 * a messy and unpleasant business. Signals can be generated by the KILL
3 * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
4 * In all cases control eventually passes to check_sig() to see which processes
5 * can be signaled. The actual signaling is done by sig_proc().
7 * The entry points into this file are:
8 * do_sigaction: perform the SIGACTION system call
9 * do_sigpending: perform the SIGPENDING system call
10 * do_sigprocmask: perform the SIGPROCMASK system call
11 * do_sigreturn: perform the SIGRETURN system call
12 * do_sigsuspend: perform the SIGSUSPEND system call
13 * do_kill: perform the KILL system call
14 * do_alarm: perform the ALARM system call by calling set_alarm()
15 * set_alarm: tell the clock task to start or stop a timer
16 * do_pause: perform the PAUSE system call
17 * ksig_pending: the kernel notified about pending signals
18 * sig_proc: interrupt or terminate a signaled process
19 * check_sig: check which processes to signal with sig_proc()
20 * check_pending: check if a pending signal can now be delivered
23 #include "pm.h"
24 #include <sys/stat.h>
25 #include <sys/ptrace.h>
26 #include <minix/callnr.h>
27 #include <minix/endpoint.h>
28 #include <minix/com.h>
29 #include <signal.h>
30 #include <sys/resource.h>
31 #include <sys/sigcontext.h>
32 #include <string.h>
33 #include "mproc.h"
34 #include "param.h"
36 FORWARD _PROTOTYPE( int dump_core, (struct mproc *rmp) );
37 FORWARD _PROTOTYPE( void unpause, (int pro, int for_trace) );
38 FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map) );
39 FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp) );
41 /*===========================================================================*
42 * do_sigaction *
43 *===========================================================================*/
44 PUBLIC int do_sigaction()
46 int r;
47 struct sigaction svec;
48 struct sigaction *svp;
50 if (m_in.sig_nr == SIGKILL) return(OK);
51 if (m_in.sig_nr < 1 || m_in.sig_nr > _NSIG) return (EINVAL);
52 svp = &mp->mp_sigact[m_in.sig_nr];
53 if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) {
54 r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp,
55 who_e, (vir_bytes) m_in.sig_osa, (phys_bytes) sizeof(svec));
56 if (r != OK) return(r);
59 if ((struct sigaction *) m_in.sig_nsa == (struct sigaction *) NULL)
60 return(OK);
62 /* Read in the sigaction structure. */
63 r = sys_datacopy(who_e, (vir_bytes) m_in.sig_nsa,
64 PM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec));
65 if (r != OK) return(r);
67 if (svec.sa_handler == SIG_IGN) {
68 sigaddset(&mp->mp_ignore, m_in.sig_nr);
69 sigdelset(&mp->mp_sigpending, m_in.sig_nr);
70 sigdelset(&mp->mp_catch, m_in.sig_nr);
71 sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
72 } else if (svec.sa_handler == SIG_DFL) {
73 sigdelset(&mp->mp_ignore, m_in.sig_nr);
74 sigdelset(&mp->mp_catch, m_in.sig_nr);
75 sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
76 } else if (svec.sa_handler == SIG_MESS) {
77 if (! (mp->mp_flags & PRIV_PROC)) return(EPERM);
78 sigdelset(&mp->mp_ignore, m_in.sig_nr);
79 sigaddset(&mp->mp_sig2mess, m_in.sig_nr);
80 sigdelset(&mp->mp_catch, m_in.sig_nr);
81 } else {
82 sigdelset(&mp->mp_ignore, m_in.sig_nr);
83 sigaddset(&mp->mp_catch, m_in.sig_nr);
84 sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
86 mp->mp_sigact[m_in.sig_nr].sa_handler = svec.sa_handler;
87 sigdelset(&svec.sa_mask, SIGKILL);
88 mp->mp_sigact[m_in.sig_nr].sa_mask = svec.sa_mask;
89 mp->mp_sigact[m_in.sig_nr].sa_flags = svec.sa_flags;
90 mp->mp_sigreturn = (vir_bytes) m_in.sig_ret;
91 return(OK);
94 /*===========================================================================*
95 * do_sigpending *
96 *===========================================================================*/
97 PUBLIC int do_sigpending()
99 mp->mp_reply.reply_mask = (long) mp->mp_sigpending;
100 return OK;
103 /*===========================================================================*
104 * do_sigprocmask *
105 *===========================================================================*/
106 PUBLIC int do_sigprocmask()
108 /* Note that the library interface passes the actual mask in sigmask_set,
109 * not a pointer to the mask, in order to save a copy. Similarly,
110 * the old mask is placed in the return message which the library
111 * interface copies (if requested) to the user specified address.
113 * The library interface must set SIG_INQUIRE if the 'act' argument
114 * is NULL.
116 * KILL and STOP can't be masked.
119 int i;
121 mp->mp_reply.reply_mask = (long) mp->mp_sigmask;
123 switch (m_in.sig_how) {
124 case SIG_BLOCK:
125 sigdelset((sigset_t *)&m_in.sig_set, SIGKILL);
126 sigdelset((sigset_t *)&m_in.sig_set, SIGSTOP);
127 for (i = 1; i <= _NSIG; i++) {
128 if (sigismember((sigset_t *)&m_in.sig_set, i))
129 sigaddset(&mp->mp_sigmask, i);
131 break;
133 case SIG_UNBLOCK:
134 for (i = 1; i <= _NSIG; i++) {
135 if (sigismember((sigset_t *)&m_in.sig_set, i))
136 sigdelset(&mp->mp_sigmask, i);
138 check_pending(mp);
139 break;
141 case SIG_SETMASK:
142 sigdelset((sigset_t *) &m_in.sig_set, SIGKILL);
143 sigdelset((sigset_t *) &m_in.sig_set, SIGSTOP);
144 mp->mp_sigmask = (sigset_t) m_in.sig_set;
145 check_pending(mp);
146 break;
148 case SIG_INQUIRE:
149 break;
151 default:
152 return(EINVAL);
153 break;
155 return OK;
158 /*===========================================================================*
159 * do_sigsuspend *
160 *===========================================================================*/
161 PUBLIC int do_sigsuspend()
163 mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */
164 mp->mp_sigmask = (sigset_t) m_in.sig_set;
165 sigdelset(&mp->mp_sigmask, SIGKILL);
166 mp->mp_flags |= SIGSUSPENDED;
167 check_pending(mp);
168 return(SUSPEND);
171 /*===========================================================================*
172 * do_sigreturn *
173 *===========================================================================*/
174 PUBLIC int do_sigreturn()
176 /* A user signal handler is done. Restore context and check for
177 * pending unblocked signals.
180 int r;
182 mp->mp_sigmask = (sigset_t) m_in.sig_set;
183 sigdelset(&mp->mp_sigmask, SIGKILL);
185 r = sys_sigreturn(who_e, (struct sigmsg *) m_in.sig_context);
186 check_pending(mp);
187 return(r);
190 /*===========================================================================*
191 * do_kill *
192 *===========================================================================*/
193 PUBLIC int do_kill()
195 /* Perform the kill(pid, signo) system call. */
197 return check_sig(m_in.pid, m_in.sig_nr);
200 /*===========================================================================*
201 * ksig_pending *
202 *===========================================================================*/
203 PUBLIC int ksig_pending()
205 /* Certain signals, such as segmentation violations originate in the kernel.
206 * When the kernel detects such signals, it notifies the PM to take further
207 * action. The PM requests the kernel to send messages with the process
208 * slot and bit map for all signaled processes. The File System, for example,
209 * uses this mechanism to signal writing on broken pipes (SIGPIPE).
211 * The kernel has notified the PM about pending signals. Request pending
212 * signals until all signals are handled. If there are no more signals,
213 * NONE is returned in the process number field.
215 int proc_nr_e;
216 sigset_t sig_map;
218 while (TRUE) {
219 int r;
220 /* get an arbitrary pending signal */
221 if((r=sys_getksig(&proc_nr_e, &sig_map)) != OK)
222 panic(__FILE__,"sys_getksig failed", r);
223 if (NONE == proc_nr_e) { /* stop if no more pending signals */
224 break;
225 } else {
226 int proc_nr_p;
227 if(pm_isokendpt(proc_nr_e, &proc_nr_p) != OK)
228 panic(__FILE__,"sys_getksig strange process", proc_nr_e);
229 handle_ksig(proc_nr_e, sig_map); /* handle the received signal */
230 /* If the process still exists to the kernel after the signal
231 * has been handled ...
233 if ((mproc[proc_nr_p].mp_flags & (IN_USE | ZOMBIE)) == IN_USE)
235 if((r=sys_endksig(proc_nr_e)) != OK) /* ... tell kernel it's done */
236 panic(__FILE__,"sys_endksig failed", r);
240 return(SUSPEND); /* prevents sending reply */
243 /*===========================================================================*
244 * handle_ksig *
245 *===========================================================================*/
246 PRIVATE void handle_ksig(proc_nr_e, sig_map)
247 int proc_nr_e;
248 sigset_t sig_map;
250 register struct mproc *rmp;
251 int i, proc_nr;
252 pid_t proc_id, id;
254 if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0)
255 return;
256 rmp = &mproc[proc_nr];
257 if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE)
258 return;
259 proc_id = rmp->mp_pid;
260 mp = &mproc[0]; /* pretend signals are from PM */
261 mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */
263 /* Check each bit in turn to see if a signal is to be sent. Unlike
264 * kill(), the kernel may collect several unrelated signals for a
265 * process and pass them to PM in one blow. Thus loop on the bit
266 * map. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0 to indicate
267 * a broadcast to the recipient's process group. For SIGKILL, use
268 * proc_id -1 to indicate a systemwide broadcast.
270 for (i = 1; i <= _NSIG; i++) {
271 if (!sigismember(&sig_map, i)) continue;
272 switch (i) {
273 case SIGINT:
274 case SIGQUIT:
275 case SIGWINCH:
276 id = 0; break; /* broadcast to process group */
277 default:
278 id = proc_id;
279 break;
281 check_sig(id, i);
285 /*===========================================================================*
286 * do_alarm *
287 *===========================================================================*/
288 PUBLIC int do_alarm()
290 /* Perform the alarm(seconds) system call. */
291 return(set_alarm(who_e, m_in.seconds));
294 /*===========================================================================*
295 * set_alarm *
296 *===========================================================================*/
297 PUBLIC int set_alarm(proc_nr_e, sec)
298 int proc_nr_e; /* process that wants the alarm */
299 int sec; /* how many seconds delay before the signal */
301 /* This routine is used by do_alarm() to set the alarm timer. It is also used
302 * to turn the timer off when a process exits with the timer still on.
304 clock_t ticks; /* number of ticks for alarm */
305 clock_t exptime; /* needed for remaining time on previous alarm */
306 clock_t uptime; /* current system time */
307 int remaining; /* previous time left in seconds */
308 int s;
309 int proc_nr_n;
311 if(pm_isokendpt(proc_nr_e, &proc_nr_n) != OK)
312 return EINVAL;
314 /* First determine remaining time of previous alarm, if set. */
315 if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
316 if ( (s=getuptime(&uptime)) != OK)
317 panic(__FILE__,"set_alarm couldn't get uptime", s);
318 exptime = *tmr_exp_time(&mproc[proc_nr_n].mp_timer);
319 remaining = (int) ((exptime - uptime + (HZ-1))/HZ);
320 if (remaining < 0) remaining = 0;
321 } else {
322 remaining = 0;
325 /* Tell the clock task to provide a signal message when the time comes.
327 * Large delays cause a lot of problems. First, the alarm system call
328 * takes an unsigned seconds count and the library has cast it to an int.
329 * That probably works, but on return the library will convert "negative"
330 * unsigneds to errors. Presumably no one checks for these errors, so
331 * force this call through. Second, If unsigned and long have the same
332 * size, converting from seconds to ticks can easily overflow. Finally,
333 * the kernel has similar overflow bugs adding ticks.
335 * Fixing this requires a lot of ugly casts to fit the wrong interface
336 * types and to avoid overflow traps. ALRM_EXP_TIME has the right type
337 * (clock_t) although it is declared as long. How can variables like
338 * this be declared properly without combinatorial explosion of message
339 * types?
341 ticks = (clock_t) (HZ * (unsigned long) (unsigned) sec);
342 if ( (unsigned long) ticks / HZ != (unsigned) sec)
343 ticks = LONG_MAX; /* eternity (really TMR_NEVER) */
345 if (ticks != 0) {
346 pm_set_timer(&mproc[proc_nr_n].mp_timer, ticks,
347 cause_sigalrm, proc_nr_e);
348 mproc[proc_nr_n].mp_flags |= ALARM_ON;
349 } else if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
350 pm_cancel_timer(&mproc[proc_nr_n].mp_timer);
351 mproc[proc_nr_n].mp_flags &= ~ALARM_ON;
353 return(remaining);
356 /*===========================================================================*
357 * cause_sigalrm *
358 *===========================================================================*/
359 PRIVATE void cause_sigalrm(tp)
360 struct timer *tp;
362 int proc_nr_n;
363 register struct mproc *rmp;
365 /* get process from timer */
366 if(pm_isokendpt(tmr_arg(tp)->ta_int, &proc_nr_n) != OK) {
367 printf("PM: ignoring timer for invalid endpoint %d\n",
368 tmr_arg(tp)->ta_int);
369 return;
372 rmp = &mproc[proc_nr_n];
374 if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return;
375 if ((rmp->mp_flags & ALARM_ON) == 0) return;
376 rmp->mp_flags &= ~ALARM_ON;
377 check_sig(rmp->mp_pid, SIGALRM);
380 /*===========================================================================*
381 * do_pause *
382 *===========================================================================*/
383 PUBLIC int do_pause()
385 /* Perform the pause() system call. */
387 mp->mp_flags |= PAUSED;
388 return(SUSPEND);
391 /*===========================================================================*
392 * sig_proc *
393 *===========================================================================*/
394 PUBLIC void sig_proc(rmp, signo)
395 register struct mproc *rmp; /* pointer to the process to be signaled */
396 int signo; /* signal to send to process (1 to _NSIG) */
398 /* Send a signal to a process. Check to see if the signal is to be caught,
399 * ignored, tranformed into a message (for system processes) or blocked.
400 * - If the signal is to be transformed into a message, request the KERNEL to
401 * send the target process a system notification with the pending signal as an
402 * argument.
403 * - If the signal is to be caught, request the KERNEL to push a sigcontext
404 * structure and a sigframe structure onto the catcher's stack. Also, KERNEL
405 * will reset the program counter and stack pointer, so that when the process
406 * next runs, it will be executing the signal handler. When the signal handler
407 * returns, sigreturn(2) will be called. Then KERNEL will restore the signal
408 * context from the sigcontext structure.
409 * If there is insufficient stack space, kill the process.
412 vir_bytes new_sp;
413 int s;
414 int slot;
415 int sigflags;
417 slot = (int) (rmp - mproc);
418 if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
419 printf("PM: signal %d sent to %s process %d\n",
420 signo, (rmp->mp_flags & ZOMBIE) ? "zombie" : "dead", slot);
421 panic(__FILE__,"", NO_NUM);
423 if (rmp->mp_fs_call != PM_IDLE || rmp->mp_fs_call2 != PM_IDLE)
425 sigaddset(&rmp->mp_sigpending, signo);
426 rmp->mp_flags |= PM_SIG_PENDING;
427 /* keep the process from running */
428 sys_nice(rmp->mp_endpoint, PRIO_STOP);
429 return;
432 if ((rmp->mp_flags & TRACED) && signo != SIGKILL) {
433 /* A traced process has special handling. */
434 unpause(slot, TRUE /*for_trace*/);
435 stop_proc(rmp, signo); /* a signal causes it to stop */
436 return;
438 /* Some signals are ignored by default. */
439 if (sigismember(&rmp->mp_ignore, signo)) {
440 return;
442 if (sigismember(&rmp->mp_sigmask, signo)) {
443 /* Signal should be blocked. */
444 sigaddset(&rmp->mp_sigpending, signo);
445 return;
447 #if ENABLE_SWAP
448 if (rmp->mp_flags & ONSWAP) {
449 /* Process is swapped out, leave signal pending. */
450 sigaddset(&rmp->mp_sigpending, signo);
451 swap_inqueue(rmp);
452 return;
454 #endif
455 sigflags = rmp->mp_sigact[signo].sa_flags;
456 if (sigismember(&rmp->mp_catch, signo)) {
457 /* Stop process from running before we do stack calculations. */
458 sys_nice(rmp->mp_endpoint, PRIO_STOP);
459 if (rmp->mp_flags & SIGSUSPENDED)
460 rmp->mp_sigmsg.sm_mask = rmp->mp_sigmask2;
461 else
462 rmp->mp_sigmsg.sm_mask = rmp->mp_sigmask;
463 rmp->mp_sigmsg.sm_signo = signo;
464 rmp->mp_sigmsg.sm_sighandler =
465 (vir_bytes) rmp->mp_sigact[signo].sa_handler;
466 rmp->mp_sigmsg.sm_sigreturn = rmp->mp_sigreturn;
467 if ((s=get_stack_ptr(rmp->mp_endpoint, &new_sp)) != OK)
468 panic(__FILE__,"couldn't get new stack pointer (for sig)",s);
469 rmp->mp_sigmsg.sm_stkptr = new_sp;
471 /* Make room for the sigcontext and sigframe struct. */
472 new_sp -= sizeof(struct sigcontext)
473 + 3 * sizeof(char *) + 2 * sizeof(int);
475 if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
476 goto doterminate;
478 rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
479 if (sigflags & SA_NODEFER)
480 sigdelset(&rmp->mp_sigmask, signo);
481 else
482 sigaddset(&rmp->mp_sigmask, signo);
484 if (sigflags & SA_RESETHAND) {
485 sigdelset(&rmp->mp_catch, signo);
486 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
488 sigdelset(&rmp->mp_sigpending, signo);
490 /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND
491 * call.
493 if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {
494 rmp->mp_flags &= ~(PAUSED | WAITING | SIGSUSPENDED);
495 setreply(slot, EINTR);
497 /* Ask the kernel to deliver the signal */
498 s= sys_sigsend(rmp->mp_endpoint, &rmp->mp_sigmsg);
499 if (s != OK)
500 panic(__FILE__, "sys_sigsend failed", s);
502 /* Done */
503 return;
506 /* Ask FS to unpause the process. Deliver the signal when FS is
507 * ready.
509 unpause(slot, FALSE /*!for_trace*/);
510 return;
512 else if (sigismember(&rmp->mp_sig2mess, signo)) {
514 /* Mark event pending in process slot and send notification. */
515 sigaddset(&rmp->mp_sigpending, signo);
516 notify(rmp->mp_endpoint);
517 return;
520 doterminate:
521 /* Signal should not or cannot be caught. Take default action. */
522 if (sigismember(&ign_sset, signo)) return;
524 rmp->mp_sigstatus = (char) signo;
525 if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) {
526 #if ENABLE_SWAP
527 if (rmp->mp_flags & ONSWAP) {
528 /* Process is swapped out, leave signal pending. */
529 sigaddset(&rmp->mp_sigpending, signo);
530 swap_inqueue(rmp);
531 return;
533 #endif
535 s= dump_core(rmp);
536 if (s == SUSPEND)
537 return;
539 /* Not dumping core, just call exit */
541 pm_exit(rmp, 0, FALSE /*!for_trace*/); /* terminate process */
544 /*===========================================================================*
545 * check_sig *
546 *===========================================================================*/
547 PUBLIC int check_sig(proc_id, signo)
548 pid_t proc_id; /* pid of proc to sig, or 0 or -1, or -pgrp */
549 int signo; /* signal to send to process (0 to _NSIG) */
551 /* Check to see if it is possible to send a signal. The signal may have to be
552 * sent to a group of processes. This routine is invoked by the KILL system
553 * call, and also when the kernel catches a DEL or other signal.
556 register struct mproc *rmp;
557 int count; /* count # of signals sent */
558 int error_code;
560 if (signo < 0 || signo > _NSIG) return(EINVAL);
562 /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
563 if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
565 /* Search the proc table for processes to signal.
566 * (See forkexit.c aboutpid magic.)
568 count = 0;
569 error_code = ESRCH;
570 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
571 if (!(rmp->mp_flags & IN_USE)) continue;
572 if ((rmp->mp_flags & ZOMBIE) && signo != 0) continue;
574 /* Check for selection. */
575 if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
576 if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
577 if (proc_id == -1 && rmp->mp_pid <= INIT_PID) continue;
578 if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
580 /* Do not kill servers and drivers when broadcasting SIGKILL. */
581 if (proc_id == -1 && signo == SIGKILL &&
582 (rmp->mp_flags & PRIV_PROC)) continue;
584 /* Check for permission. */
585 if (mp->mp_effuid != SUPER_USER
586 && mp->mp_realuid != rmp->mp_realuid
587 && mp->mp_effuid != rmp->mp_realuid
588 && mp->mp_realuid != rmp->mp_effuid
589 && mp->mp_effuid != rmp->mp_effuid) {
590 error_code = EPERM;
591 continue;
594 count++;
595 if (signo == 0) continue;
597 /* 'sig_proc' will handle the disposition of the signal. The
598 * signal may be caught, blocked, ignored, or cause process
599 * termination, possibly with core dump.
601 sig_proc(rmp, signo);
603 if (proc_id > 0) break; /* only one process being signaled */
606 /* If the calling process has killed itself, don't reply. */
607 if ((mp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return(SUSPEND);
608 return(count > 0 ? OK : error_code);
611 /*===========================================================================*
612 * check_pending *
613 *===========================================================================*/
614 PUBLIC void check_pending(rmp)
615 register struct mproc *rmp;
617 /* Check to see if any pending signals have been unblocked. The
618 * first such signal found is delivered.
620 * If multiple pending unmasked signals are found, they will be
621 * delivered sequentially.
623 * There are several places in this file where the signal mask is
624 * changed. At each such place, check_pending() should be called to
625 * check for newly unblocked signals.
628 int i;
630 for (i = 1; i <= _NSIG; i++) {
631 if (sigismember(&rmp->mp_sigpending, i) &&
632 !sigismember(&rmp->mp_sigmask, i)) {
633 sigdelset(&rmp->mp_sigpending, i);
634 sig_proc(rmp, i);
635 break;
640 /*===========================================================================*
641 * unpause *
642 *===========================================================================*/
643 PRIVATE void unpause(pro, for_trace)
644 int pro; /* which process number */
645 int for_trace; /* for tracing */
647 /* A signal is to be sent to a process. If that process is hanging on a
648 * system call, the system call must be terminated with EINTR. Possible
649 * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
650 * First check if the process is hanging on an PM call. If not, tell FS,
651 * so it can check for READs and WRITEs from pipes, ttys and the like.
653 register struct mproc *rmp;
654 int r;
656 rmp = &mproc[pro];
658 /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */
659 if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {
660 rmp->mp_flags &= ~(PAUSED | WAITING | SIGSUSPENDED);
661 setreply(pro, EINTR);
662 return;
665 /* Process is not hanging on an PM call. Ask FS to take a look. */
666 if (for_trace)
668 if (rmp->mp_fs_call != PM_IDLE)
669 panic( __FILE__, "unpause: not idle", rmp->mp_fs_call);
670 rmp->mp_fs_call= PM_UNPAUSE_TR;
672 else
674 if (rmp->mp_fs_call2 != PM_IDLE)
675 panic( __FILE__, "unpause: not idle", rmp->mp_fs_call2);
676 rmp->mp_fs_call2= PM_UNPAUSE;
678 r= notify(FS_PROC_NR);
679 if (r != OK) panic("pm", "unpause: unable to notify FS", r);
682 /*===========================================================================*
683 * dump_core *
684 *===========================================================================*/
685 PRIVATE int dump_core(rmp)
686 register struct mproc *rmp; /* whose core is to be dumped */
688 /* Make a core dump on the file "core", if possible. */
690 int r, proc_nr, proc_nr_e, parent_waiting;
691 pid_t procgrp;
692 vir_bytes current_sp;
693 struct mproc *p_mp;
694 clock_t t[5];
696 printf("dumpcore for %d / %s\n", rmp->mp_pid, rmp->mp_name);
698 /* Do not create core files for set uid execution */
699 if (rmp->mp_realuid != rmp->mp_effuid) return OK;
701 /* Make sure the stack segment is up to date.
702 * We don't want adjust() to fail unless current_sp is preposterous,
703 * but it might fail due to safety checking. Also, we don't really want
704 * the adjust() for sending a signal to fail due to safety checking.
705 * Maybe make SAFETY_BYTES a parameter.
707 if ((r= get_stack_ptr(rmp->mp_endpoint, &current_sp)) != OK)
708 panic(__FILE__,"couldn't get new stack pointer (for core)", r);
709 adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
711 /* Tell FS about the exiting process. */
712 if (rmp->mp_fs_call != PM_IDLE)
713 panic(__FILE__, "dump_core: not idle", rmp->mp_fs_call);
714 rmp->mp_fs_call= PM_DUMPCORE;
715 r= notify(FS_PROC_NR);
716 if (r != OK) panic(__FILE__, "dump_core: unable to notify FS", r);
718 /* Also perform most of the normal exit processing. Informing the parent
719 * has to wait until we know whether the coredump was successful or not.
722 proc_nr = (int) (rmp - mproc); /* get process slot number */
723 proc_nr_e = rmp->mp_endpoint;
725 /* Remember a session leader's process group. */
726 procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
728 /* If the exited process has a timer pending, kill it. */
729 if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr_e, (unsigned) 0);
731 /* Do accounting: fetch usage times and accumulate at parent. */
732 if((r=sys_times(proc_nr_e, t)) != OK)
733 panic(__FILE__,"pm_exit: sys_times failed", r);
735 p_mp = &mproc[rmp->mp_parent]; /* process' parent */
736 p_mp->mp_child_utime += t[0] + rmp->mp_child_utime; /* add user time */
737 p_mp->mp_child_stime += t[1] + rmp->mp_child_stime; /* add system time */
739 /* Tell the kernel the process is no longer runnable to prevent it from
740 * being scheduled in between the following steps. Then tell FS that it
741 * the process has exited and finally, clean up the process at the kernel.
742 * This order is important so that FS can tell drivers to cancel requests
743 * such as copying to/ from the exiting process, before it is gone.
745 sys_nice(proc_nr_e, PRIO_STOP); /* stop the process */
747 if(proc_nr_e != FS_PROC_NR) /* if it is not FS that is exiting.. */
749 if (rmp->mp_flags & PRIV_PROC)
751 /* destroy system processes without waiting for FS */
752 if((r= sys_exit(rmp->mp_endpoint)) != OK)
753 panic(__FILE__, "pm_exit: sys_exit failed", r);
755 /* Just send a SIGCHLD. Dealing with waidpid is too complicated
756 * here.
758 p_mp = &mproc[rmp->mp_parent]; /* process' parent */
759 sig_proc(p_mp, SIGCHLD);
761 /* Zombify to avoid calling sys_endksig */
762 rmp->mp_flags |= ZOMBIE;
765 else
767 printf("PM: FS died\n");
768 return SUSPEND;
771 /* Pending reply messages for the dead process cannot be delivered. */
772 rmp->mp_flags &= ~REPLY;
774 /* Keep the process around until FS is finished with it. */
776 /* If the process has children, disinherit them. INIT is the new parent. */
777 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
778 if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
779 /* 'rmp' now points to a child to be disinherited. */
780 rmp->mp_parent = INIT_PROC_NR;
781 parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
782 if (parent_waiting && (rmp->mp_flags & ZOMBIE))
784 tell_parent(rmp);
785 real_cleanup(rmp);
790 /* Send a hangup to the process' process group if it was a session leader. */
791 if (procgrp != 0) check_sig(-procgrp, SIGHUP);
793 return SUSPEND;