-
Notifications
You must be signed in to change notification settings - Fork 160
/
signal.c
190 lines (110 loc) · 5.23 KB
/
signal.c
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
/*
ANSI C also specifies signal, here are the POSIX extensions.
POSIX recommends `sigaction` instead of `signal`.
To send arbitrary signals to a process from a terminal, consider using the `kill` utility
(it does more than killing via a SIGTERM, as in general it sends any signal to a process)
Also consider the convenient non POSIX stadardized VT100 control characters such as `<C-C>`
which generate certain signals such as `SIGTERM`.
# ANSI signals
ANSI C supports the concept of signals, and only POSIX specific features shall be discussed here.
Please look for ANSI C info for any feature used but not explained here.
Linux extends POSIX by adding new signals, Those shall not be discussed here.
# POSIX signals
Docs here: http://pubs.opengroup.org/onlinepubs/009696699/basedefs/signal.h.html
POSIX defines several signals in addition to the ANSI C signals.
As in ANSI C, each signal has the following attributes:
- general description of which conditions generate the signal
- the signal can or cannot be handled.
Most signals can be handled, but there are a few exceptions such as:
- `SIGKILL`: always kill processes, cannot be handled.
- `SIGKSTOP` and `SIGCONT`
- default action to take
For signals that can be handled, you can change those behavious by creating your own handlers.
The possible default behaviours are:
- T:
Abnormal termination of the process.
The process is terminated with all the consequences of `_exit()` except that the status made available to
`wait()` and `waitpid()` indicates abnormal termination by the specified signal.
Default action for most signals.
- A :Abnormal termination of the process.
[XSI] [Option Start] Additionally, implementation-defined abnormal termination actions,
such as creation of a core file, may occur. [Option End]
Linux implements concept of core dumps on those cases.
Note however that those may be turned on or off depending on the system configuration.
- I: Ignore the signal.
An important example is `SIGCHLD`, which is generated when a child terminates,
but has no effect by default, since in general killing the parent is not what
should happen on most programs.
- S: Stop the process.
Mainly `SIGSTOP`.
- C: Continue the process, if it is stopped; otherwise, ignore the signal.
Mainly `SIGCONT`.
POSIX specific signals include:
# SIGKILL
Kills program.
Cannot be handled unlike to `SIGINT` and `SIGTERM`.
# SIGQUIT
Quit program.
Used in case of abnormal termination (`A`), unlike `SIGINT` and `SIGTERM` which happen on normal temrination.
May generate a core dump https://en.wikipedia.org/wiki/Core_dump depending on system configurations.
On Ubuntu, coredumps are disabled by default. You can enable them for the current session with:
ulimit -c unlimited
on the terminal where you will run the command to enable core dumps.
The setting can be permanently changed on the `/etc/security/limits.conf` file.
The core file is binary. To interpret it you must have compiled the program with debugging
information and then use GDB on the core file and the executable as:
gcc -g -o myfile myfile.c
gdb myfile core
# SIGSTOP
Freezes program.
`ctrl+z`, in linux terminals.
Cannot be handle.
# SIGCONT
Continues a process that
# SIGHUP
Controlling terminal was killed.
This is why killing the terminal kills most process by default unless those process implement a handler.
# SIGPIPE
Process write to a pipe with no readers on other side
# SIGCHLD
Child terminated, stopped or continued.
Ignored by default.
# SIGALRM
Received after the alarm call after given no of secs.
# SIGUSR1
# SIGUSR2
Left to users to do whatever they want with. Default to `term`.
# Parent death signal
In POSIX, no signal needs to be sent to the child if the parent exits:
http://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits
In Linux, this can be achieved via the `prctl` syscall.
This may seem surprising considering that:
- parents can wait for children
- children get a NOHUP when controling process is killed
This is mentioned at: http://pubs.opengroup.org/onlinepubs/009695399/functions/exit.html
TODO what is a controlling process?
# Bibliography
- `man 7 signal`
- http://www.alexonlinux.com/signal-handling-in-linux
good intro
*/
#include "common.h"
volatile sig_atomic_t i = 0;
void signal_handler(int sig) {
i = 1;
signal(sig, signal_handler);
}
int main(void) {
signal(SIGALRM, signal_handler);
/*
# Send signal
# kill
This is done via the kill function:
int kill(pid_t pid, int sig);
*/
{
assert(kill(getpid(), SIGALRM) == 0);
}
assert(i == 1);
return EXIT_SUCCESS;
}