File: signal-handler.c

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (184 lines) | stat: -rw-r--r-- 6,467 bytes parent folder | download | duplicates (12)
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
// RUN: %check_clang_tidy %s bugprone-signal-handler %t -- -- -isystem %clang_tidy_headers

#include "signal.h"
#include "stdlib.h"
#include "stdio.h"
#include "system-other.h"

// The function should be classified as standard function even if there is
// declaration the in source file.
// FIXME: The detection works only if the first declaration is in system
// header.
int printf(const char *, ...);
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

void f_extern(void);
void f_extern_handler(int);

void handler_printf(int) {
  printf("1234");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_printf' registered here as signal handler
}

void test_printf(void) {
  signal(SIGINT, handler_printf);
}

void handler_extern(int) {
  f_extern();
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_extern' registered here as signal handler
}

void test_extern(void) {
  signal(SIGINT, handler_extern);
}

void f_ok(void) {
  abort();
}

void handler_ok(int) {
  f_ok();
}

void test_ok(void) {
  signal(SIGINT, handler_ok);
}

void f_bad(void) {
  printf("1234");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_bad' called here from 'handler_bad'
  // CHECK-NOTES: :[[@LINE+8]]:18: note: function 'handler_bad' registered here as signal handler
}

void handler_bad(int) {
  f_bad();
}

void test_bad(void) {
  signal(SIGINT, handler_bad);
}

void f_bad1(void) {
  printf("1234");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+6]]:3: note: function 'f_bad1' called here from 'f_bad2'
  // CHECK-NOTES: :[[@LINE+9]]:3: note: function 'f_bad2' called here from 'handler_bad1'
  // CHECK-NOTES: :[[@LINE+13]]:18: note: function 'handler_bad1' registered here as signal handler
}

void f_bad2(void) {
  f_bad1();
}

void handler_bad1(int) {
  f_bad2();
  f_bad1();
}

void test_bad1(void) {
  signal(SIGINT, handler_bad1);
}

void handler_abort(int) {
  abort();
}

void handler_signal(int) {
  // FIXME: It is only OK to call signal with the current signal number.
  signal(0, SIG_DFL);
}

void handler_false_condition(int) {
  if (0)
    printf("1234");
  // CHECK-NOTES: :[[@LINE-1]]:5: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_false_condition' registered here as signal handler
}

void test_false_condition(void) {
  signal(SIGINT, handler_false_condition);
}

void handler_multiple_calls(int) {
  f_extern();
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_calls' registered here as signal handler
  printf("1234");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+6]]:18: note: function 'handler_multiple_calls' registered here as signal handler
  f_extern();
  // first 'f_extern' call found only
}

void test_multiple_calls(void) {
  signal(SIGINT, handler_multiple_calls);
}

void f_recursive(void);

void handler_recursive(int) {
  f_recursive();
  printf("");
  // first 'printf' call (in f_recursive) found only
}

void f_recursive(void) {
  f_extern();
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE-8]]:3: note: function 'f_recursive' called here from 'handler_recursive'
  // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_recursive' registered here as signal handler
  printf("");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE-12]]:3: note: function 'f_recursive' called here from 'handler_recursive'
  // CHECK-NOTES: :[[@LINE+5]]:18: note: function 'handler_recursive' registered here as signal handler
  handler_recursive(2);
}

void test_recursive(void) {
  signal(SIGINT, handler_recursive);
}

void f_multiple_paths(void) {
  printf("");
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
  // CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_multiple_paths' called here from 'handler_multiple_paths'
  // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_paths' registered here as signal handler
}

void handler_multiple_paths(int) {
  f_multiple_paths();
  f_multiple_paths();
}

void test_multiple_paths(void) {
  signal(SIGINT, handler_multiple_paths);
}

void handler_function_pointer(int) {
  void (*fp)(void) = f_extern;
  // Call with function pointer is not evalauted by the check.
  (*fp)();
}

void test_function_pointer(void) {
  signal(SIGINT, handler_function_pointer);
}

void test_other(void) {
  signal(SIGINT, handler_abort);
  signal(SIGINT, handler_signal);

  signal(SIGINT, _Exit);
  signal(SIGINT, other_call);
  // CHECK-NOTES: :[[@LINE-1]]:18: warning: standard function 'other_call' may not be asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
  signal(SIGINT, f_extern_handler);
  // CHECK-NOTES: :[[@LINE-1]]:18: warning: cannot verify that external function 'f_extern_handler' is asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]

  signal(SIGINT, SIG_IGN);
  signal(SIGINT, SIG_DFL);
}