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
25 #include <sys/ptrace.h>
26 #include <minix/callnr.h>
27 #include <minix/endpoint.h>
28 #include <minix/com.h>
30 #include <sys/resource.h>
31 #include <sys/sigcontext.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 /*===========================================================================*
43 *===========================================================================*/
44 PUBLIC
int do_sigaction()
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
)
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
);
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
;
94 /*===========================================================================*
96 *===========================================================================*/
97 PUBLIC
int do_sigpending()
99 mp
->mp_reply
.reply_mask
= (long) mp
->mp_sigpending
;
103 /*===========================================================================*
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
116 * KILL and STOP can't be masked.
121 mp
->mp_reply
.reply_mask
= (long) mp
->mp_sigmask
;
123 switch (m_in
.sig_how
) {
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
);
134 for (i
= 1; i
<= _NSIG
; i
++) {
135 if (sigismember((sigset_t
*)&m_in
.sig_set
, i
))
136 sigdelset(&mp
->mp_sigmask
, i
);
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
;
158 /*===========================================================================*
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
;
171 /*===========================================================================*
173 *===========================================================================*/
174 PUBLIC
int do_sigreturn()
176 /* A user signal handler is done. Restore context and check for
177 * pending unblocked signals.
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
);
190 /*===========================================================================*
192 *===========================================================================*/
195 /* Perform the kill(pid, signo) system call. */
197 return check_sig(m_in
.pid
, m_in
.sig_nr
);
200 /*===========================================================================*
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.
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 */
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 /*===========================================================================*
245 *===========================================================================*/
246 PRIVATE
void handle_ksig(proc_nr_e
, sig_map
)
250 register struct mproc
*rmp
;
254 if(pm_isokendpt(proc_nr_e
, &proc_nr
) != OK
|| proc_nr
< 0)
256 rmp
= &mproc
[proc_nr
];
257 if ((rmp
->mp_flags
& (IN_USE
| ZOMBIE
)) != IN_USE
)
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;
276 id
= 0; break; /* broadcast to process group */
285 /*===========================================================================*
287 *===========================================================================*/
288 PUBLIC
int do_alarm()
290 /* Perform the alarm(seconds) system call. */
291 return(set_alarm(who_e
, m_in
.seconds
));
294 /*===========================================================================*
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 */
311 if(pm_isokendpt(proc_nr_e
, &proc_nr_n
) != OK
)
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;
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
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) */
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
;
356 /*===========================================================================*
358 *===========================================================================*/
359 PRIVATE
void cause_sigalrm(tp
)
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
);
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 /*===========================================================================*
382 *===========================================================================*/
383 PUBLIC
int do_pause()
385 /* Perform the pause() system call. */
387 mp
->mp_flags
|= PAUSED
;
391 /*===========================================================================*
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
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.
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
);
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 */
438 /* Some signals are ignored by default. */
439 if (sigismember(&rmp
->mp_ignore
, signo
)) {
442 if (sigismember(&rmp
->mp_sigmask
, signo
)) {
443 /* Signal should be blocked. */
444 sigaddset(&rmp
->mp_sigpending
, signo
);
448 if (rmp
->mp_flags
& ONSWAP
) {
449 /* Process is swapped out, leave signal pending. */
450 sigaddset(&rmp
->mp_sigpending
, signo
);
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
;
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
)
478 rmp
->mp_sigmask
|= rmp
->mp_sigact
[signo
].sa_mask
;
479 if (sigflags
& SA_NODEFER
)
480 sigdelset(&rmp
->mp_sigmask
, signo
);
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
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
);
500 panic(__FILE__
, "sys_sigsend failed", s
);
506 /* Ask FS to unpause the process. Deliver the signal when FS is
509 unpause(slot
, FALSE
/*!for_trace*/);
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
);
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
) {
527 if (rmp
->mp_flags
& ONSWAP
) {
528 /* Process is swapped out, leave signal pending. */
529 sigaddset(&rmp
->mp_sigpending
, signo
);
539 /* Not dumping core, just call exit */
541 pm_exit(rmp
, 0, FALSE
/*!for_trace*/); /* terminate process */
544 /*===========================================================================*
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 */
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.)
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
) {
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 /*===========================================================================*
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.
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
);
640 /*===========================================================================*
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
;
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
);
665 /* Process is not hanging on an PM call. Ask FS to take a look. */
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
;
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 /*===========================================================================*
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
;
692 vir_bytes current_sp
;
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
, ¤t_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
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
;
767 printf("PM: FS died\n");
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
))
790 /* Send a hangup to the process' process group if it was a session leader. */
791 if (procgrp
!= 0) check_sig(-procgrp
, SIGHUP
);