|
|
1.1 root 1: An Introduction to Signals Under MiNT
2:
3:
4:
5: MiNT introduces the new (to TOS) concept of a signal. If you're
6:
7: familiar with Unix/Posix signals, then MiNT signals will will be
8:
9: easy to learn; but note that there are some (not so subtle) differences
10:
11: between MiNT and Unix!
12:
13:
14:
15: What is a Signal?
16:
17:
18:
19: A signal is a small non-negative integer that represents an exceptional event;
20:
21: something that is very urgent. It's somewhat like an interrupt or
22:
23: exception to the CPU, only it's implemented in the operating system
24:
25: instead of in the hardware. Like many exceptions (bus errors, etc.) signals
26:
27: are usually fatal. Most signals can be caught by programs (so that a
28:
29: program-defined routine is called) or ignored; if a signal is caught or
30:
31: ignored, it is no longer fatal. Signals can also be blocked; a
32:
33: blocked signal is not acted upon until it is unblocked.
34:
35:
36:
37: A signal is said to be sent to a process when the exceptional
38:
39: condition related to that signal occurs, or when another process sends
40:
41: the signal with the Pkill system call. The signal is said to
42:
43: be delivered to the process when that process wakes up and
44:
45: begins to take whatever actions are appropriate for the signal. Note
46:
47: that there may be a considerable time interval between the sending of
48:
49: a signal and its delivery. For example, if process A has blocked the
50:
51: SIGHUP signal (signal 1), then no SIGHUP will be delivered to it until
52:
53: it has unblocked that signal, even if process B sends it SIGHUP with
54:
55: the Pkill system call. Note also that a signal is not
56:
57: necessarily delivered the same number of times that it is sent. If both
58:
59: process B and process C send SIGHUP to process A, when process A
60:
61: unblocks SIGHUP only one SIGHUP will be delivered. This is because signals
62:
63: are like flags; once a flag has been set (the signal is sent) setting
64:
65: the flag again will have no effect until it has been cleared (the signal
66:
67: is delivered).
68:
69:
70:
71: What Signals Are There?
72:
73:
74:
75: There are 32 possible signals, 0-31. Not all of these have been assigned
76:
77: a meaning under MiNT. Here are the ones that have been given a meaning;
78:
79: we give the symbolic name for the signal, the corresponding integer,
80:
81: and the "traditional" meaning for the process that the signal is sent to.
82:
83: Any signal not listed here should be considered as "reserved" and should not
84:
85: be used by applications.
86:
87:
88:
89: Unless otherwise noted, the default action for signals is to terminate
90:
91: the process.
92:
93:
94:
95: #define SIGNULL 0 [no default action, signal is never delivered]
96:
97: This isn't really a signal at all; it is never delivered to processes
98:
99: and has no effect. It exists only so that processes can test to see if
100:
101: a particular child process has exited, by attempting to send SIGNULL
102:
103: to the child. If the child exists, the attempt will succeed but nothing
104:
105: will be done. If the child has terminated, the caller will get an error.
106:
107: It is not possible to catch or block this signal, since it is never
108:
109: sent to processes anyway.
110:
111:
112:
113: #define SIGHUP 1
114:
115: "The terminal that you're connected to is no longer valid." This signal
116:
117: is commonly sent by, for example, window managers when the user has
118:
119: closed the window. Processes should not attempt any I/O to their
120:
121: controlling terminal after receiving this signal, and indeed should probably
122:
123: exit unless the user has specifically asked them to continue.
124:
125:
126:
127: #define SIGINT 2
128:
129: "Please stop what you're doing." This signal is sent when the user
130:
131: presses control-C. It usually means that the process should exit; interactive
132:
133: processes may wish to catch SIGINT so that the user can use it to
134:
135: break out of time-consuming tasks.
136:
137:
138:
139: #define SIGQUIT 3
140:
141: "Stop what you're doing, something's gone wrong!" This signal is sent when
142:
143: the user presses control-\. It usually indicates a desire to immediately
144:
145: abort the process because of an error that the user has noticed. It is
146:
147: generally thought to be "stronger" than SIGINT, and exiting (perhaps after
148:
149: cleaning up data structures) is an appropriate response to this.
150:
151:
152:
153: #define SIGILL 4
154:
155: "An illegal instruction has been encountered." This corresponds to the
156:
157: 680x0 illegal instruction trap, and usually indicates a very serious error;
158:
159: catching this signal is generally unwise.
160:
161:
162:
163: #define SIGTRAP 5
164:
165: "The single-step trace trap has been encountered." This corresponds to the
166:
167: 680x0 trace trap, and is usually activated (and handled) by debuggers;
168:
169: user programs shouldn't catch this.
170:
171:
172:
173: #define SIGABRT 6
174:
175: "An awful error has occured." This is commonly sent by the abort library
176:
177: function, and indicates that something has gone very, very wrong (for
178:
179: example, data structures have been unexpectedly corrupted). It is unlikely
180:
181: that anything useful can be done after this signal is sent; programs
182:
183: should not normally catch or ignore SIGABRT.
184:
185:
186:
187: #define SIGPRIV 7
188:
189: "Privilege violation." An attempt has been made to execute an instruction
190:
191: in user mode that is normally restricted to supervisor mode; this corresponds
192:
193: to the 680x0 privilege violation exception, and indicates a serious error.
194:
195:
196:
197: #define SIGFPE 8
198:
199: "Division by zero or a floating point error has occured." Processes may
200:
201: ignore or catch this signal (which corresponds to the 680x0 division by zero
202:
203: trap) and deal with it as they see fit.
204:
205:
206:
207: #define SIGKILL 9 [cannot be blocked or caught]
208:
209: "Die!" This signal will never be seen by a process; nor can processes
210:
211: block it. Sending SIGKILL is a way to be sure of killing a run-away
212:
213: process. Use it only as a last resort, since it gives the process no
214:
215: chance to clean up and exit gracefully.
216:
217:
218:
219: #define SIGBUS 10
220:
221: "Bus error." Corresponds to the 680x0 bus error exception, and indicates
222:
223: a very serious error; programs should generally not attempt to ignore
224:
225: or catch this signal.
226:
227:
228:
229: #define SIGSEGV 11
230:
231: "Illegal memory reference." Corresponds to the 680x0 address error
232:
233: exception, and indicates a very serious error; catching or ignoring this
234:
235: signal is not recommended.
236:
237:
238:
239: #define SIGSYS 12
240:
241: "Bad argument to a system call." This signal is sent when an illegal
242:
243: (usually, out of range) parameter is sent to a system call, and when that
244:
245: system call does not have any "nice" way to report errors. For example,
246:
247: Super(0L) when the system is already in supervisor mode causes SIGSYS to
248:
249: be raised. Note that the kernel does not always detect illegal/out of
250:
251: range arguments to system calls, only sometimes.
252:
253:
254:
255: #define SIGPIPE 13
256:
257: "A pipe you were writing to has no readers." Programs may catch this signal
258:
259: and attempt to exit gracefully after receiving it; note that exiting is
260:
261: appropriate because the standard output is probably no longer connected
262:
263: to anything.
264:
265:
266:
267: #define SIGALRM 14
268:
269: "The alarm you set earlier has happened." This signal is sent to processes
270:
271: when the alarm clock set by Talarm (q.v.) expires. It's very
272:
273: common to catch this signal and from the signal handler jump to a known
274:
275: point in the program; for example, to indicate a timeout while attempting
276:
277: to communicate over a serial line.
278:
279:
280:
281: #define SIGTERM 15
282:
283: "Please die." This is a polite form of SIGKILL (#9). Programs should
284:
285: respect this nice request; they may want to catch the signal to perform
286:
287: some cleanup actions, but they should then exit (since if they don't,
288:
289: the user will probably get mad and send SIGKILL later anyway...). This
290:
291: is the signal that is sent when a process is dragged to the trashcan on
292:
293: the desktop.
294:
295:
296:
297: #define SIGSTOP 17 [default action: suspend the process]
298:
299: "Suspend yourself." This signal is sent to a process when it should be
300:
301: stopped temporarily. SIGSTOP is used primarily by debuggers and similar
302:
303: programs; suspensions requested directly by the user usually are signalled
304:
305: by SIGTSTP (q.v.) This signal cannot be ignored, blocked, or caught.
306:
307:
308:
309: #define SIGTSTP 18 [default action: suspend the process]
310:
311: "The user is asking you to suspend yourself." This signal is sent immediately
312:
313: when the user presses the control-Z key, and is sent when the process tries
314:
315: to read a control-Y key in cooked mode (for a delayed stop). In both cases,
316:
317: the process should suspend itself. Since this is the default action, no
318:
319: special handling is normally required, although some programs may wish to
320:
321: save the screen state and restore it when they are unsuspended.
322:
323:
324:
325: #define SIGCONT 19 [default action: continue a stopped
326:
327: process]
328:
329: "You are being restarted after having been suspended." This signal is
330:
331: sent by shells to resume a suspended process. If the process is not
332:
333: suspended, the signal does nothing. This signal cannot be blocked, but
334:
335: it *is* possible to install a handler for it (this is rarely necessary,
336:
337: though).
338:
339:
340:
341: #define SIGCHLD 20 [default action: no action taken]
342:
343: "One of your children has been suspended or has exited." This signal is
344:
345: sent by the kernel to the parent of any process that is terminated (either
346:
347: because of a signal or by a Pterm, Pterm0, or Ptermres system call) or
348:
349: which is suspended because of a signal. Programs that are concerned with the
350:
351: status of their children (for example, shells) may wish to catch this signal;
352:
353: after a SIGCHLD has been received, the Pwait3 system call may be
354:
355: used to determine exactly which child has exited or been suspended.
356:
357: Note that the Psigaction system call may be used to force SIGCHLD to be
358:
359: delivered only when a child process terminates (so that suspension of
360:
361: child processes, for example via job control, does not raise SIGCHLD.
362:
363:
364:
365: #define SIGTTIN 21 [default action: suspended the process]
366:
367: "Attempt to read from a terminal you don't own." This signal is sent to
368:
369: any process that attempts to do input from a terminal with a different
370:
371: process group than their own. Usually, this happens if the user has started
372:
373: the job in the background; the process will be suspended until the user
374:
375: explicitly brings it to the foreground with the appropriate shell command
376:
377: (at which time the shell will reset the terminal's process group and
378:
379: send the stopped process a SIGCONT signal to tell it to continue).
380:
381: [NOTE: in fact, SIGTTIN and SIGTTOU are sent to all processes in the same
382:
383: process group as the process that attempted to do the i/o; this is for
384:
385: compatibility with Unix, and it simplifies the implementation of job
386:
387: control shells.]
388:
389:
390:
391: #define SIGTTOU 22 [default action: suspend the process]
392:
393: "Attempt to write to a terminal that you don't own." Similar to SIGTTIN (q.v.).
394:
395: Processes should normally respect the user's job control and should
396:
397: override or ignore SIGTTOU only in situations where a very critical error
398:
399: has occured and a message must be printed immediately.
400:
401:
402:
403: #define SIGXCPU 24
404:
405: "Your CPU time limit has been exhausted." Sent to processes when they have
406:
407: consumed more than the maximum number of milliseconds of CPU time allowed
408:
409: by the Psetlimit() system call. The signal will continue to be sent to
410:
411: the process until it exits; if a process does catch this signal, it should
412:
413: do whatever clean up actions are necessary and then terminate.
414:
415:
416:
417: #define SIGWINCH 28 [default action: no action taken]
418:
419: "The window you were running in has changed size." This signal is sent
420:
421: to processes by some window managers to indicate that the user has changed
422:
423: the size of the window the process is running in. If the process cares
424:
425: about the window size, it may catch this signal and use an Fcntl call
426:
427: to inquire about the new window size when the signal is received.
428:
429: (See the documentation for Fcntl for details.)
430:
431:
432:
433: #define SIGUSR1 29
434:
435: #define SIGUSR2 30
436:
437:
438:
439: These two signals are reserved for applications, which may define whatever
440:
441: meaning they wish for them. Note, however, that these signals do
442:
443: terminate processes by default, so don't send them to a process which
444:
445: isn't prepared to deal with them.
446:
447:
448:
449:
450:
451: System Calls Dealing With Signals
452:
453:
454:
455:
456:
457: WORD
458:
459: Pkill( WORD pid, WORD sig )
460:
461:
462:
463: If pid > 0, then the given signal (see the numbers above) is sent to the
464:
465: process with that pid.
466:
467: If pid == 0, then the given signal is sent to all members of the process
468:
469: group of the process making the Pkill call. This includes, of course,
470:
471: the process itself.
472:
473: If pid < 0, the signal is sent to all members of process group (-pid).
474:
475:
476:
477: Returns:
478:
479: 0 for successful sending of the signal
480:
481: (Note that if the current process is a recipient of the signal,
482:
483: and the signal proves to be fatal, then Pkill will never return.)
484:
485: ERANGE if "sig" is less than 0 or greater than 31
486:
487: EFILNF if pid > 0 and the indicated process has terminated or does not
488:
489: exist, or if pid < 0 and there are no processes in the given
490:
491: process group
492:
493: EACCDN if the sending process is not authorized to send signals to
494:
495: the specified receiving process or group (for example, they
496:
497: belong to different users)
498:
499:
500:
501:
502:
503: #define SIG_DFL (0L)
504:
505: #define SIG_IGN (1L)
506:
507:
508:
509: LONG
510:
511: Psignal( WORD sig, LONG handler )
512:
513:
514:
515: Change the handling of the indicated signal.
516:
517:
518:
519: If "handler" is SIG_DFL, then the default action for the signal will occur when
520:
521: the signal is delivered to the current process.
522:
523:
524:
525: If "handler" is SIG_IGN, then the signal will be ignored by the process, and
526:
527: delivery of the signal will have no noticeable effect (in particular, the
528:
529: signal will not interrupt the Pause system call, q.v.). If the signal
530:
531: is pending at the time of the Psignal call, it is discarded.
532:
533:
534:
535: If "handler" is any other value, it is assumed to be the address of a
536:
537: user function that will be called when the signal is delivered to the
538:
539: process. The user function is called with a single LONG argument on
540:
541: the stack, which is the number of the signal being delivered (this is done
542:
543: so that processes may use the same handler for a number of different
544:
545: signals). While the signal is being handled, it is blocked from delivery;
546:
547: thus, signal handling is "reliable" (unlike Version 7 and early System V
548:
549: Unix implementations, in which delivery of a second signal while it
550:
551: was being handled could kill the process). Also note that, unlike some
552:
553: versions of Unix, the signal handling is *not* reset to the default action
554:
555: before the handler is called; it remains set to the given signal handler.
556:
557:
558:
559: The signal handler must either return (via a normal 680x0 rts instruction)
560:
561: or call the Psigreturn system call to indicate when signal handling is
562:
563: complete; in both cases, the signal will be unblocked. Psigreturn also
564:
565: performs some internal clean-up of the kernel stack that is necessary if
566:
567: the signal handler is not planning to return (for example, if the C
568:
569: longjmp() function is to be used to continue execution at another point
570:
571: in the program).
572:
573:
574:
575: Signal handlers may make any GEMDOS, BIOS, or XBIOS system calls freely.
576:
577: GEM AES and VDI calls should not be made in a signal handler.
578:
579:
580:
581: Note that calling Psignal to change behavior of a signal has the side
582:
583: effect of unmasking that signal, so that delivery is possible. This is done
584:
585: so that processes may, while handling a signal, reset the behavior and
586:
587: send themselves another instance of the signal, for example in order
588:
589: to suspend themselves while handling a job control signal.
590:
591:
592:
593: Signal handling is preserved across Pfork and Pvfork calls. Signals
594:
595: that are ignored by the parent are also ignored by the child after a Pexec
596:
597: call; signals that were being caught for handling in a function are reset
598:
599: in the child to the default behavior.
600:
601:
602:
603: Returns:
604:
605: The old value of handler on success.
606:
607: ERANGE if sig < 1 or sig > 31
608:
609: EACCDN if sig cannot be caught by the user (i.e. SIGKILL or SIGSTOP)
610:
611:
612:
613: Bugs:
614:
615: Signal handling can be nested only a small (around 3) number of times,
616:
617: i.e. if 4 signals are delivered to a process, and the process has established
618:
619: handlers for all 4, and none of the handlers has returned or called
620:
621: Psigreturn, then there is a very good chance of a stack overflow killing
622:
623: the process off. In practice, this is unlikely to happen.
624:
625:
626:
627:
628:
629: LONG
630:
631: Psigblock( LONG amask )
632:
633:
634:
635: Block receipt of some signals. The "amask" argument is added to the
636:
637: current set of signals being masked, i.e. the new set of blocked signals
638:
639: is the union of the old set and the set represented by amask. Sets of
640:
641: blocked signals are represented by a 32 bit unsigned long quantity, with
642:
643: bit (1L << sig) set if signal "sig" is to be blocked, and clear if not.
644:
645:
646:
647: Blocked signals remain blocked across Pfork and Pvfork calls. For Pexec
648:
649: calls, children always start out with an empty set of blocked signals,
650:
651: regardless of which signals are blocked in the parent.
652:
653:
654:
655: Returns:
656:
657: The old set of blocked signals (i.e. the set as it was before amask
658:
659: was added to it).
660:
661:
662:
663: NOTE: Certain signals (SIGKILL, SIGSTOP, SIGCONT) cannot be blocked;
664:
665: if the corresponding bits are set in amask, the kernel will clear them
666:
667: but will not report an error.
668:
669:
670:
671:
672:
673: LONG
674:
675: Psigsetmask( LONG mask )
676:
677:
678:
679: Decide which signals are to be blocked from delivery. Unlike Psigblock
680:
681: (which adds to the set of blocked signals) Psigsetmask changes the
682:
683: entire set, replacing the old set of blocked signals with the one
684:
685: specified in "mask". As with Psigblock, signal n is blocked from
686:
687: delivery if bit (1L << n) is set in mask. Note that certain signals
688:
689: cannot be blocked, and if the corresponding bits are set in the
690:
691: mask the kernel will clear them.
692:
693:
694:
695: Returns:
696:
697: The old set of blocked signals.
698:
699:
700:
701: Usage:
702:
703: Typically, Psigblock and Psigsetmask are used together to temporarily
704:
705: block signals, e.g.:
706:
707:
708:
709: oldmask = Psigblock( (1L << SIGINT) );
710:
711: ... do some things with SIGINT blocked from delivery ...
712:
713: (void) Psigsetmask(oldmask);
714:
715:
716:
717:
718:
719:
720:
721: LONG
722:
723: Psigpending()
724:
725:
726:
727: Give an indication of what signals are pending (i.e. have been sent to
728:
729: the process but not yet delivered, probably because they are blocked
730:
731: from delivery).
732:
733:
734:
735: Returns:
736:
737: A 32 bit unsigned long representing the set of signals that are pending.
738:
739: Signal n is pending if bit (1L << n) is set in the returned value.
740:
741:
742:
743:
744:
745: void
746:
747: Psigreturn()
748:
749:
750:
751: Terminate signal handling. This call should be used by any signal
752:
753: handler that is not planning to return to the kernel (i.e. if the
754:
755: handler is going to execute a non-local jump to another point in the
756:
757: program). It cleans up the signal delivery stack and unblocks the
758:
759: signal that was being delivered. Calling Psigreturn when no signal
760:
761: is being delivered is harmless.
762:
763:
764:
765: Bugs:
766:
767: Calling Psigreturn from a signal handler, and then actually returning
768:
769: from that handler, is likely to produce extremely unpleasant results.
770:
771: Don't do it.
772:
773:
774:
775:
776:
777: void
778:
779: Pause()
780:
781:
782:
783: Wait until a signal is delivered. This call will return after any (non-fatal)
784:
785: signal has been delivered to the process. Note that signals that are being
786:
787: ignored are never delivered.
788:
789:
790:
791:
792:
793: void
794:
795: Psigpause( LONG mask )
796:
797:
798:
799: Block the set of signals specified by "mask", and then wait until
800:
801: a signal is delivered. This call will return after any (non-fatal)
802:
803: signal has been delivered to the process. Before returning, the signal
804:
805: mask is restored to its original value.
806:
807:
808:
809:
810:
811:
812:
813: struct sigaction {
814:
815: LONG sa_handler;
816:
817: LONG sa_mask;
818:
819: WORD sa_flags;
820:
821: #define SA_NOCLDSTOP 1;
822:
823: }
824:
825:
826:
827: WORD
828:
829: Psigaction( WORD sig, struct sigaction *act, struct sigaction *act )
830:
831:
832:
833: Like Psignal, this call changes the handling of the indicated signal.
834:
835: If "act" is non-zero, it is a pointer to a structure which describes
836:
837: the new signal handling behavior, as follows:
838:
839:
840:
841: sa_handler is the function to be called when the signal is delivered,
842:
843: or SIG_DFL, or SIG_IGN. For further information about
844:
845: signal handling functions, see Psignal.
846:
847: sa_mask is a set of additional signals to mask while the signal
848:
849: is being delivered. The signal itself is always masked,
850:
851: but sometimes it might be desireable to mask some
852:
853: other signals as well; this allows a "prioritization"
854:
855: of signals
856:
857: sa_flags extra flags which can affect the behavior of the
858:
859: signal. This field should normally be set to 0.
860:
861: If "sig" is SIGCHLD and "flags" is SA_NOCLDSTOP,
862:
863: then the SIGCHLD signal will not be delivered to
864:
865: this process when one of its children are stopped.
866:
867:
868:
869: If "oact" is non-zero, then the old signal handling behavior is
870:
871: copied into "oact" and returned.
872:
873:
874:
875: Returns:
876:
877: 0 on success
878:
879: ERANGE if sig < 1 or sig > 31
880:
881: EACCDN if sig cannot be caught by the user
882:
883:
884:
885: Usage:
886:
887: If "sig" is a valid signal, the call:
888:
889: foo = Psignal(sig, newfunc)
890:
891: is equivalent to:
892:
893: struct sigaction newact, oact;
894:
895: newact->sa_mask=0L;
896:
897: newact->sa_flags=0;
898:
899: newact->sa_handler = newfunc;
900:
901: Psigaction(sig, &newact, &oact);
902:
903: foo = oact->sa_handler;
904:
905:
906:
907:
908:
909: LONG
910:
911: Talarm( LONG s )
912:
913:
914:
915: If s > 0, schedule a SIGALRM signal to occur in s seconds. This alarm
916:
917: will replace any previously scheduled alarm.
918:
919: If s = 0, cancel any previously scheduled alarm.
920:
921: If s < 0, inquire about a scheduled alarm but do not change it.
922:
923:
924:
925: Returns:
926:
927: If an alarm was previously scheduled, returns the number of seconds remaining
928:
929: until that previously scheduled alarm. Otherwise, returns 0.
930:
931:
932:
933: Bugs:
934:
935: Internal calculations are done in milliseconds, not seconds, so the returned
936:
937: value is not exactly accurate.
938:
939: For the same reason, setting an alarm more than 2 million seconds or so
940:
941: into the future will not work correctly.
942:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.