-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsignals.tex
684 lines (609 loc) · 27 KB
/
signals.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
include(`macros.m4')
\pdfbookmark[0]{signals}{signals}
\begin{slide}
\sltitle{Contents}
\slidecontents{5}
\end{slide}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{slide}
\sltitle{Introduction to signals}
\begin{itemize}
\item for notifying a process of asynchronous events, and for exception handling
\item mechanism of an interrupt available in user level
\item signal categories:
\begin{itemize}
\item \emsl{asynchronous events} happening independently of the main program
flow, e.g. a signal sent from another process, a timer expiration
(\texttt{SIGALRM}), terminal disconnect (\texttt{SIGHUP}), or pressing
\texttt{Ctrl-C} (\texttt{SIGINT})
\item \emsl{exceptions} caused by a running process, e.g.
attempt to access a restricted area of memory (\texttt{SIGSEGV})
\end{itemize}
\end{itemize}
\end{slide}
\hlabel{SIGNALS}
\begin{itemize}
\item Interrupts can be viewed as a mean of communication between the CPU and
the OS kernel while signals are for communication between the kernel and
processes.
\item After returning from the handler, if that happens, the process continues
exactly from the place where the interruption happened.
\item Historically, signals were provided as a mechanism to forcefully terminate
processes. That is why the function for sending signals is called
\funnm{kill}.
\item A nice example of an asynchronous event is to send a \texttt{SIGUSR1} to
the \texttt{dd} command on Linux to print its progress to standard error output.
Start \texttt{dd} first, then send a couple of \texttt{USR1} signals its way,
like this:
\begin{verbatim}
$ kill -USR1 $(pgrep -f "dd if=/dev/zero of=/dev/null")
\end{verbatim}
You will see something like this:
\begin{verbatim}
$ dd if=/dev/zero of=/dev/null
9179287+0 records in
9179286+0 records out
4699794432 bytes (4.7 GB, 4.4 GiB) copied, 1.79083 s, 2.6 GB/s
14211424+0 records in
14211423+0 records out
7276248576 bytes (7.3 GB, 6.8 GiB) copied, 2.76889 s, 2.6 GB/s
\end{verbatim}
\end{itemize}
On BSD systems, there is the \texttt{SIGINFO} signal used for that, usually
mapped to \texttt{Ctrl-T}. It looks as follows there:
\begin{verbatim}
freebsd$ dd if=/dev/zero of=/dev/null
load: 0.00 cmd: dd 12108 [runnable] 1.09r 0.07u 0.94s 14% 888k
39941+0 records in
39940+0 records out
20449280 bytes transferred in 1.054782 secs (19387211 bytes/sec)
load: 0.08 cmd: dd 12108 [runnable] 2.00r 0.15u 1.72s 21% 912k
74278+0 records in
74278+0 records out
38030336 bytes transferred in 1.965972 secs (19344292 bytes/sec)
^C104684+0 records in
104683+0 records out
53597696 bytes transferred in 2.774283 secs (19319477 bytes/sec)
\end{verbatim}
%%%%%
\begin{slide}
\sltitle{Introduction to signals (continued)}
\begin{itemize}
\item it is the simplest inter process communication -- it only carries
information that an event happened
\begin{itemize}
\item there is a real-time POSIX extension that allows for more information,
more on that later
\end{itemize}
\item mostly processed asynchronously -- a signal interrupts the current process
flow and a \emph{signal handler} is invoked
\item signals are identified by numbers, represented by names like
\texttt{SIGSEGV}, \texttt{SIGCHLD}, or \texttt{SIGKILL}
\item name are usually \texttt{\#define}s, see \texttt{/usr/include/signal.h} or
\texttt{/usr/include/sys/signal.h}
\end{itemize}
\end{slide}
\begin{itemize}
\item The real-time extension is POSIX-1003.1b.
\pageref{REALTIMEEXTENSIONS}.
\item You can process signals in a synchronous way, see \funnm{sigwait}() on
page \pageref{SIGWAIT}.
\end{itemize}
%%%%%
\pdfbookmark[1]{kill}{kill}
\begin{slide}
\sltitle{Sending signals}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{kill}(pid\_t \emph{pid}, int \emph{sig});}
]]])
\begin{itemize}
\item sends signal \emph{\texttt{sig}} to a process or a process group
based on value of \emph{\texttt{pid}}:
\begin{itemize}
\item \texttt{> 0} \dots{} to process with \emph{\texttt{pid}}
\item \texttt{== 0} \dots{} to all processes in the same group
\item \texttt{== -1} \dots{} to all aside from system processes
\item \texttt{< -1} \dots{} to processes in a group \texttt{abs(pid)}
\end{itemize}
\item \texttt{sig == 0} means the system only checks whether the process has
enough privileges to send a signal without sending it
\item whether a process may send other process a signal depends on UID of both
processes
\end{itemize}
\end{slide}
\hlabel{KILLSYSCALL}
\begin{itemize}
\item Traditionally, process with EUID~==~0 can send a signal to any other
process. However, some systems optionally provide fine grain privileges and the
situation there is different even for root. That is out of scope for this class
though. \item Sending a signal to another process:
\begin{itemize}
\item Linux, Solaris: RUID or EUID of the process that sent the signal must
match the RUID or saved UID of the target process.
\item FreeBSD: EUID of the processes must match
\end{itemize}
\item Example: \example{signals/killing-myself.c}
\item Using \texttt{0} as \emph{\texttt{sig}} may be used for a simple check for
the specific process existence, see \example{signals/check-existence.c}.
No signal is sent in that case.
\end{itemize}
%%%%%
\pdfbookmark[1]{Handling signals}{sighandle}
\begin{slide}
\sltitle{Handling signals}
\begin{itemize}
\item unless a process sets it otherwise, each signal triggers a specific
default action, one of:
\begin{itemize}
\item terminate the process (\emsl{exit})
\item terminate and dump a core (\emsl{core})
\item ignore the signal (\emsl{ignore})
\item stop the process (\emsl{stop})
\item resume the process (\emsl{continue})
\end{itemize}
\item process can either choose to ignore a specific signal\dots
\item \dots{}or can handle the signal via a user-defined function,
called a \emph{handler}
\end{itemize}
Signals \texttt{SIGKILL} and \texttt{SIGSTOP} \emsl{always} trigger an implicit
action, i.e. exit or stop, respectively.
\end{slide}
\begin{itemize}
\item Creating a core dump means to store the contents of the process virtual
address space to a file. Usually such file has a word \texttt{core} in its
file name. Some systems, e.g. macOS, may not generate core dumps by default even
if its for signals with default core dump action. In that case,
\texttt{ulimit -c unlimited} usually helps, and it affects the current shell
only. See the present shell limits with \texttt{ulimit -a}.
\item Most of the signals implicitly terminate the process, some create a core
dump on top of that to enable a post-mortem analysis.
\item The reason why \funnm{exec}() replaces all user set handlers to its
implicit action (see also page \pageref{EXEC}) is obvious -- code of the
original handlers no longer exists after the \funnm{exec}() call finishes.
\item You can learn the signal numbers and their names using the \texttt{-l}
option for the \texttt{kill(1)} command. Without the argument, it will print
the list of all signals with their corresponding numbers. Example:
\begin{verbatim}
$ kill -l SIGPIPE
13
\end{verbatim}
\item For each signal, you can learn what is its implicit action by checking a
manual page for function \funnm{signal}() or possibly for \emph{signal.h}. On
Linux distributions, it is usually in the \texttt{signal(7)} manual page,
accessible via \texttt{man 7 signal}.
\end{itemize}
%%%%%
\pdfbookmark[1]{Signal listing}{siglist}
\begin{slide}
\sltitle{Signal listing (1)}
We could divide signals into a few groups\dots
\emsl{Detected errors:}
\begin{tabular}{ll}
\texttt{SIGBUS} & bus error, e.g. wrong alignment (core) \\
\texttt{SIGFPE} & floating point exception (core) \\
\texttt{SIGILL} & illegal instructions (core) \\
\texttt{SIGSEGV} & segmentation violation (core) \\
\texttt{SIGPIPE} & write on a pipe with no reader (exit) \\
\texttt{SIGSYS} & non-existent system call invoked (core) \\
\texttt{SIGXCPU} & CPU time limit exceeded (core) \\
\texttt{SIGXFSZ} & file size limit exceeded (core)\\
\end{tabular}
\end{slide}
\begin{itemize}
\item Those signals are generated on an error in a program.
\item \hlabel{SHELLRETVALUEFORSIGNALS} For the first four signals --
\texttt{SIGBUS}, \texttt{SIGFPE}, \texttt{SIGILL}, and \texttt{SIGSEGV} the
standard does not specify what exactly has to be the reason but usually those
are errors detected by hardware. Try the following examples, and check the
return value with ``\texttt{kill -l \$?}'': \example{signals/sigsegv.c},
\example{signals/div-by-zero.c}.
\par The Unix shell convention is that if a program is killed by a signal,
\texttt{\$?} will be \texttt{128} plus the signal number (\texttt{Ctrl+\bs}
sends any foreground process a \texttt{SIGQUIT} signal):
\begin{verbatim}
$ sleep 99
^\Quit: 3
$ echo $?
131
$ kill -l 131
QUIT
$ kill -l $((131 - 128))
QUIT
\end{verbatim}
\item \hlabel{SPECIALSIGNALS} \emsl{For those four signals, there are some
special rules as well} (for details, see section \emph{2.4 Signal Concepts} in
SUSv4):
\begin{itemize}
\item If set as ignored by function \funnm{sigaction}(), the program behavior
after such a signal is delivered is undefined.
\item The behavior of a process is undefined after it returns from a
signal-catching function.
\item If such a signal is masked while the signal is being delivered, the
program behavior is undefined.
\end{itemize}
\item Bottom line is that if a hardware generated error is real (i.e. the signal
is not sent via \funnm{kill} or similar), the process may never get
over that error at all. It is not safe to ignore such errors, continue after
returning from a handler, or mask such signals. You can catch such signals
though, the standard does not prohibit that. However, if you do, you should do
so only to deal with the situation and exit from the handler (see above).
You can check \example{signals/catch-SIGSEGV.c}. More information and another
example can be found on page \pageref{THREADS_SIGWAIT}.
\item Note: if the standard specifies any behavior as \emph{undefined}, it means
that whatever happens does not violate the standard. So, if you trigger such a
behavior and your computer burns down or even flies off to the Moon, possibly
still in flames, that does not violate the standard either.
\end{itemize}
\begin{slide}
\sltitle{Signal listing (2)}
\emsl{Signals generated by a user or application:}
\begin{tabular}{ll}
\texttt{SIGABRT} & abort program (core) \\
\texttt{SIGHUP} & terminal line hangup (exit) \\
\texttt{SIGINT} & interrupt program via \texttt{Ctrl-C} (exit) \\
\texttt{SIGKILL} & kill program (exit, \emsl{cannot be caught or ignored})\\
\texttt{SIGQUIT} & quit program via \texttt{Ctrl-\bs} (core) \\
\texttt{SIGTERM} & software termination signal (exit) \\
\texttt{SIGUSR1} & user-defined signal 1 (exit) \\
\texttt{SIGUSR2} & user-defined signal 2 (exit) \\
\end{tabular}
\end{slide}
\begin{itemize}
\item Signal \texttt{SIGHUP} is often used as a way to let a daemon know its
configuration file changed and that it should re-read it.
\item \texttt{SIGINT} and \texttt{SIGQUIT} are usually generated from a terminal
via \texttt{Ctrl-C} and \texttt{Ctrl-\bs}, respectively, and could be redefined
using the command \texttt{stty} or via a function \funnm{tcsetattr}().
\item In order to generate core files, your system and settings must allow it.
Check the \texttt{ulimit} command and associated system call.
\item \hlabel{SIGKILL} As \texttt{SIGKILL} cannot be handled, use it only if you
know what you are doing. For example, if a running process does not respond to
user input nor any other signal. Many applications, mainly daemons, rely on the
fact that they are sent \texttt{SIGTERM} on termination, which they often handle
and perform actions before exit. For example, flushing the database, removing
temporary files and file locks, etc. So, do not use \texttt{SIGKILL} right away
only because "it's the simplest way to kill a process" as you might run in
trouble.
\item Example on using \texttt{SIGQUIT} on Solaris (a standalone \texttt{sleep}
program is used to avoid invoking a shell built-in):
\begin{verbatim}
$ /usr/bin/sleep 10
^\Quit (core dumped)
$ mdb core
Loading modules: [ libc.so.1 ld.so.1 ]
> $c
libc.so.1`__nanosleep+0x15(8047900, 8047908)
libc.so.1`sleep+0x35(a)
main+0xbc(2, 8047970, 804797c)
_start+0x7a(2, 8047a74, 8047a7a, 0, 8047a7d, 8047b91)
>
\end{verbatim}
\item \texttt{SIGTERM} is the default signal for command \texttt{kill(1)}.
\item \texttt{SIGUSR1} and \texttt{SIGUSR2} are not used by any system call and
are available for use to the user. These are used to e.g. dump internal state
of a daemon to a file, display statistics of the program run so far, etc.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{Signal listing (3)}
\emsl{Job control:}
\begin{tabular}{ll}
\texttt{SIGCHLD} & child status has changed (ignore)\\
\texttt{SIGCONT} & continue after stop (continue) \\
\texttt{SIGSTOP} & stop (stop; \emsl{cannot be caught or ignored}) \\
\texttt{SIGTSTP} & stop from terminal \texttt{Ctrl-Z} (stop) \\
\texttt{SIGTTIN} & background read attempted from control terminal (stop) \\
\texttt{SIGTTOU} & background write attempted to control terminal (stop) \\
\end{tabular}
\end{slide}
\begin{itemize}
\item Those used to be part of a non-mandatory POSIX extension but now they are
required by POSIX.1-2008. See also page \pageref{UNIXSTANDARDS}.
\item Only one process at any given time can read from its process group control
terminal but multiple processes can write to it at the same time.
\item Stopping a process group from a terminal, usually via \texttt{Ctrl-Z}, is
done with signal \texttt{SIGTSTP}, not \texttt{SIGSTOP}; a program thus can
catch the signal. \hlabel{SIGTSTP}
\item the \texttt{SIGCHLD} signal is always received by the parent
(no matter if \texttt{wait()} or \texttt{waitpid()} is used) unless
explicitly ignored. See \example{signals/sigchld.c}
\item If you write a program that prints anything onto its standard output and
execute it in the background, you notice that usually the text shows up on your
terminal (meaning no \texttt{SIGTTOU} was sent as that would have stopped the
process on the controlling terminal write attempt). It is because the signal is
sent (or not) by the terminal driver, and \texttt{stty} will tell you what is
the current setting. If you see no \texttt{tostop}, you can set it up with
``\texttt{stty tostop}'' and see the difference.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{Signal listing (4)}
\emsl{Timers:}
\begin{tabular}{ll}
\texttt{SIGALRM} & timer expired (exit) \\
\texttt{SIGPROF} & profiling timer alarm (exit; see \funnm{setitimer}(2)) \\
\texttt{SIGVTALRM} & virtual time alarm (exit; also see \funnm{setitimer}(2)) \\
\end{tabular}
\emsl{Miscellaneous:}
\begin{tabular}{ll}
\texttt{SIGPOLL} & event occurred on explicitly watched file descriptor (exit)\\
\texttt{SIGTRAP} & trace trap (core) \\
\texttt{SIGURG} & urgent condition present on socket (ignore) \\
\end{tabular}
\end{slide}
\begin{itemize}
\item \texttt{SIGALRM} and related function \funnm{alarm} is used for setting
timer alarms, useful for implementation of timeouts, for example.
\item The timers set by \texttt{alarm()} are not inherited across fork,
however the signal disposition is.
\end{itemize}
%%%%%
ifdef([[[NOSPELLCHECK]]], [[[
\pdfbookmark[1]{sigaction}{sigaction}
]]])
\begin{slide}
\sltitle{Setting actions for signals}
ifdef([[[NOSPELLCHECK]]], [[[
\begin{minipage}{\slidewidth}\vspace{-1\baselineskip}\texttt{\begin{tabbing}
int \funnm{sigaction}(\=int \emph{sig},
const struct sigaction *\emph{act},\\\> struct sigaction *\emph{oact});
\end{tabbing}}
]]])
\end{minipage}
\begin{itemize}
\item assigns an action \emph{\texttt{act}} for a signal \emph{\texttt{sig}},
previous setting is returned in \emph{\texttt{*oact}}, if \emph{\texttt{oact}}
is non-zero
\item structure \texttt{sigaction} contains:
\begin{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\item \texttt{void (*\emph{sa\_handler})(int)} \dots{} \texttt{SIG\_DFL},
]]])
\texttt{SIG\_IGN}, or a handler address (i.e. a handler function name)
\item ifdef([[[NOSPELLCHECK]]], [[[\texttt{sigset\_t \emph{sa\_mask}}]]])
\dots{} signals blocked while in
handler; plus \emph{\texttt{sig}} is blocked by default
\item ifdef([[[NOSPELLCHECK]]], [[[\texttt{int \emph{sa\_flags}}]]])
\dots{} \texttt{SA\_RESETHAND} (handler
is reset to \texttt{SIG\_DFL} at the moment the signal is delivered),
\texttt{SA\_RESTART} (restart pending calls), \texttt{SA\_NODEFER}
(do not block \emph{\texttt{sig}} while in handler)
\end{itemize}
\end{itemize}
\end{slide}
\begin{itemize}
\item for manipulating signal sets, use \funnm{sigaddset}(),
\funnm{sigdelset}(), \funnm{sigemptyset}(), \funnm{sigfillset}(),
\funnm{sigismember}()
\item If \texttt{act == NULL} you only get the present setting and nothing is
changed. If not interested in previous setting, use \texttt{NULL} for
\emph{\texttt{oact}}.
\item If \texttt{SA\_RESTART} is not set, the system call interrupted by the
signal will return an error with \texttt{errno} set to \texttt{EINTR} (some
calls actually return directly the \texttt{errno} value but that is not relevant
now). However, resetting the call will not work for all system calls. You
should consult the documentation for your system if you intend to use it.
On Linux, check the \texttt{signal(7)} manual page. Example:
\example{signals/interrupted-read.c}.
\item Beware of deadlocks (will be discussed in the chapter on synchronization).
If you set \texttt{SA\_NODEFER}, your handler needs to be reentrant.
\item \hlabel{ASYNCSIGNALSAFE} \emsl{You should only use functions in a safe way
from a handler}. By safe it is meant either use reentrant functions or you need
to make sure the signal is not delivered in the wrong time (for example, the
signal is delivered within a function and the same function is called from the
handler, and the function is not ready for that). Minimal set of functions
that must be ifdef([[[NOSPELLCHECK]]], [[[\emsl{\emph{async-signal-safe}}]]])
is listed in SUSv4 in section \emph{System Interfaces: General Information
$\Rightarrow$ Signal Concepts $\Rightarrow$ Signal Actions (2.4.3)}. Systems
can extend the list, of course. Whether a function is safe to use in a signal
handler or not should be documented in its manual page. On Linux, see
the \texttt{signal-safety(7)} manual page and also check what it says about
\texttt{printf}.
\item Using static data and/or locking in a function would generally be a
problem for its asynchronous signal safety. It can lead to corrupt data,
deadlocks, etc. As the set of functions safe to use in a handler is limited,
one way to use the signals is only to set a global variable in the handler and
test it later, for example in a loop that processes some events. As the
function waiting for an event is typically interruptible by a signal (see
above), setting the global variable and testing it later does not experience any
real delay.
Example: \example{signals/event-loop.c}.
\item There is also a simplified signal facility \funnm{signal}(). We recommend
to use \funnm{sigaction}() only. Behavior of \funnm{signal}() is not specified
with threads, for example. It can also behave in a very different way on
different systems, some keep the handler set after delivering the signal, some
reset it to \texttt{SIG\_DFL}. Check \example{signals/signal-vs-sigaction.c} if
interested.
\item \hlabel{REALTIMEEXTENSIONS} If your system supports a part of POSIX.1b
called \emph{Realtime Signals Extension} (RTS), it is possible to use the
extension if you use flag \texttt{SA\_SIGINFO}. In that case a
\texttt{sa\_sigaction} member of the structure \texttt{sigaction} must be used
for the handler, not \texttt{sa\_handler}. The new handler has three parameters
and it is possible to learn the PID of a signalling process, its UID, and more.
See manual page \texttt{signal.h(3HEAD)} on Linux or Solaris, the online SUS
specification of the header file, or the book [POSIX.4], page
\pageref{REF_PROGRAMMING}. More information is also on page \pageref{POSIX} and
\pageref{SIGWAITINFO}. Examples: \example{signals/siginfo.c},
\example{signals/sigqueue.c}.
\item \hlabel{IGNORE_SIG_CHLD} By ignoring \texttt{SIG\_CHILD} you say you will
not wait for child processes and the system will still not accumulate zombies.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{Example: setting time limit for read}
\setlength{\baselineskip}{0.8\baselineskip}
\begin{alltt}
void handler(int sig)
\{ write(2," !!! TIMEOUT !!! \bs{}n", 17); \}
int main(void)
\{
char buf[1024]; struct sigaction act; int sz;
act.sa\_handler = handler;
\emprg{sigemptyset}(&act.sa\_mask);
act.sa\_flags = 0;
\emprg{sigaction}(SIGALRM, &act, NULL);
\emprg{alarm}(5);
sz = read(0, buf, 1024);
\emprg{alarm}(0);
if (sz > 0)
write(1, buf, sz);
return (0);
\}
\end{alltt}
\end{slide}
\hlabel{SIGALRM}
\begin{itemize}
\item You can also use timers with a finer granularity provided by
\funnm{setitimer}() and \funnm{getitimer}() functions. After the timer expires,
a process is sent a signal based on the value of the first argument
\emph{which}:
\begin{itemize}
\item \texttt{ITIMER\_REAL} \dots{} timer decrements in real time, and
\texttt{SIGALRM} is used.
\item \texttt{ITIMER\_VIRTUAL} \dots{} timer decrements in process virtual time
which runs only when the process is executing. A signal \texttt{SIGVTALRM} is
used.
\item \texttt{ITIMER\_PROF} \dots{} timer decrements both in process virtual
time and when the system is running on behalf of the process, and
\texttt{SIGPROF} is used.
\end{itemize}
\item Note that in the example above and also in the source code examples we use
\funnm{write}() system call to write the text. Functions like \funnm{printf}()
are generally not safe to use in signal handlers, see page
\pageref{ASYNCSIGNALSAFE}. Also check \texttt{signal-safety(7)} manual page on
any Linux distribution, \funnm{printf}() is even discussed in there.
\item Example: \example{signals/alarm.c}
\end{itemize}
%%%%%
ifdef([[[NOSPELLCHECK]]], [[[
\pdfbookmark[1]{sigprocmask, sigpending}{sigblock}
]]])
\begin{slide}
\sltitle{Signal blocking}
\begin{itemize}
\item blocked signals are delivered to the process after getting unblocked again
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\begin{minipage}{\slidewidth}\texttt{\begin{tabbing}
int \funnm{sigprocmask}(\=int \emph{how}, const sigset\_t *\emph{set},\\
\>sigset\_t *\emph{oset});
\end{tabbing}}
\end{minipage}
]]])
\begin{itemize}
\item sets the blocked signal mask and returns the old one
\item \emph{how} -- \texttt{SIG\_BLOCK} adds signals to block,
\texttt{SIG\_UNBLOCK} for removing signals, for a complete mask change
use \texttt{SIG\_SETMASK}
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{sigpending}(sigset\_t *\emph{set});}
]]])
\begin{itemize}
\item returns signals pending for delivery
\end{itemize}
\end{slide}
\hlabel{SIGPROCMASK}
\begin{itemize}
\item The system silently ignores attempts to block \texttt{KILL} and
\texttt{STOP}.
\item It is a difference to ignore and block a signal. A signal ignored will
never be delivered to the process, while a blocked signal is remembered by the
kernel and is delivered if the process unblocks it.
\item It is implementation dependent if a signal received multiple times while
blocked will be delivered only once or multiple times after unblocking.
\item If POSIX.4 extension is used (see page
\pageref{REALTIMEEXTENSIONS} and the use of \texttt{SA\_SIGINFO}), signals are
delivered through a queue and multiple signals are never squeezed into one
delivery.
\item Both arguments \emph{\texttt{oset}} and \emph{set} may be \texttt{NULL}.
If both are \texttt{NULL} in the same invocation of the function, nothing
happens.
\item \texttt{sigpending} sets the set in the argument to the pending mask. \\
Once the signal is unblocked after \texttt{sigpending()} call, the handler
will not be called. See \example{signals/sigpending.c}.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{Example: blocking signals}
\setlength{\baselineskip}{0.8\baselineskip}
\begin{alltt}
sigset\_t sigs, osigs; struct sigaction sa = \{ 0 \};
sigfillset(&sigs); \emprg{sigprocmask}(SIG\_BLOCK, &sigs, &osigs);
switch(cpid = fork()) \{
case -1:
\emprg{sigprocmask}(SIG\_SETMASK, &osigs, NULL);
...
case 0: /* Child */
sa.sa\_handler = h\_cld;
\emprg{sigaction}(SIGINT, &sa, NULL);
\emprg{sigprocmask}(SIG\_SETMASK, &osigs, NULL);
...
default: /* Parent */
\emprg{sigprocmask}(SIG\_SETMASK, &osigs, NULL);
...
\}
\end{alltt}
\end{slide}
\begin{itemize}
\item \hlabel{SIGNALBLOCKINGEXAMPLE} The example shows a situation when a child
needs to use a different signal handler from its parent. If you just changed
the handler in the child without blocking the signals before \funnm{fork}()
a potential race would have been created -- a child would have run for a short
time with an unwanted handler. Note that \funnm{fork}() does not change the
signal mask, see page \pageref{FORK}.
\item Out of simplicity we block all the signals in the example even that on
pages \pageref{SPECIALSIGNALS} and \pageref{THREADS_SIGWAIT} it is explained why
it is not a good idea.
\end{itemize}
%%%%%
\hlabel{SIGWAIT}
ifdef([[[NOSPELLCHECK]]], [[[
\pdfbookmark[1]{pause, sigsuspend, sigwait}{sigwait}
]]])
\begin{slide}
\sltitle{Waiting for a signal}
\texttt{int \funnm{pause}(void);}
\begin{itemize}
\item suspends the caller until delivery of a signal that is not blocked or
ignored
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{sigsuspend}(const sigset\_t *\emph{sigmask});}
]]])
\begin{itemize}
\item like \funnm{pause}(), also temporarily changes the blocked signal mask
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{sigwait}(const sigset\_t *\emph{set}, int *\emph{sig});}
]]])
\begin{itemize}
\item waits for a signal from \emph{set} (must be blocked) and puts the signal
number to \emph{\texttt{sig}}.
\item the signal handler is not called
\end{itemize}
\end{slide}
\begin{itemize}
\item When in \funnm{pause}() or \funnm{sigsuspend}(), a signal not blocked will
call a handler if one is set, and the signal catching function returns unless
the process is terminated by the signal.
\item With \funnm{sigwait}(), you can implement a synchronous signal
handling. First, a process blocks signals it is interested in, then when
convenient, it waits for them or just checks whether there are some pending
using \funnm{sigpending}().
\item The \funnm{sigwait}() function was added with POSIX-1003.1c
extensions (threads) and you should use this function when dealing with signals
in the multithreaded application. As other POSIX thread functions, it returns
an error number directly, and 0 on success.
\item \hlabel{SIGWAITINFO} There are also similar functions \funnm{sigwaitinfo}()
and \funnm{sigtimedwait}() defined with the POSIX-1003.1\emsl{b} extension
(real-time). They work in a similar way but set \texttt{errno} on failure and
it is possible to get more information upon signal delivery using a structure
\texttt{siginfo\_t}, see page \pageref{REALTIMEEXTENSIONS}.
\item Example (a signal is used for synchronization of two processes
communicating via a shared memory): \example{signals/sigwait.c}
\item Do not use for synchronous signals like \texttt{SIGSEGV}, \texttt{SIGILL},
etc. More on that on pages \pageref{SPECIALSIGNALS} and
\pageref{THREADS_SIGWAIT}.
\end{itemize}
\endinput