blob: 61346b1487485743ed71e6f50e80e61cb44cb050 [file] [log] [blame]
Dave Allisonf4b80bc2014-05-14 15:41:25 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Bilyan Borisovbb661c02016-04-04 16:27:32 +010017#ifdef ART_TARGET_ANDROID
Dave Allisonf4b80bc2014-05-14 15:41:25 -070018#include <android/log.h>
Dave Allison69dfe512014-07-11 17:11:58 +000019#else
20#include <stdarg.h>
21#include <iostream>
22#endif
23
Dave Allisonf4b80bc2014-05-14 15:41:25 -070024#include <dlfcn.h>
Luis Hector Chavez33cac0f2017-04-06 14:18:09 -070025#include <errno.h>
Josh Gao99875e92017-04-17 15:58:36 -070026#include <pthread.h>
Dave Allisonf4b80bc2014-05-14 15:41:25 -070027#include <signal.h>
28#include <stdio.h>
29#include <stdlib.h>
Luis Hector Chavez33cac0f2017-04-06 14:18:09 -070030#include <string.h>
Josh Gao85a78cf2017-03-20 16:26:42 -070031
Josh Gaod32d79d2018-02-26 14:29:25 -080032#include <algorithm>
Luis Hector Chavez33cac0f2017-04-06 14:18:09 -070033#include <initializer_list>
Igor Murashkin5573c372017-11-16 13:34:30 -080034#include <mutex>
Josh Gaod32d79d2018-02-26 14:29:25 -080035#include <type_traits>
Josh Gao85a78cf2017-03-20 16:26:42 -070036#include <utility>
Dave Allisonf4b80bc2014-05-14 15:41:25 -070037
Dave Allisoncefcea82014-09-16 10:01:01 -070038#include "sigchain.h"
39
Dave Allison69dfe512014-07-11 17:11:58 +000040#if defined(__APPLE__)
41#define _NSIG NSIG
Dave Allison38680092014-08-29 12:29:34 -070042#define sighandler_t sig_t
Josh Gaodd241ae2017-03-20 14:17:23 -070043
44// Darwin has an #error when ucontext.h is included without _XOPEN_SOURCE defined.
45#define _XOPEN_SOURCE
Dave Allison69dfe512014-07-11 17:11:58 +000046#endif
47
Josh Gaodd241ae2017-03-20 14:17:23 -070048#include <ucontext.h>
49
Josh Gao85a78cf2017-03-20 16:26:42 -070050// libsigchain provides an interception layer for signal handlers, to allow ART and others to give
51// their signal handlers the first stab at handling signals before passing them on to user code.
52//
53// It implements wrapper functions for signal, sigaction, and sigprocmask, and a handler that
54// forwards signals appropriately.
55//
56// In our handler, we start off with all signals blocked, fetch the original signal mask from the
57// passed in ucontext, and then adjust our signal mask appropriately for the user handler.
58//
59// It's somewhat tricky for us to properly handle some flag cases:
60// SA_NOCLDSTOP and SA_NOCLDWAIT: shouldn't matter, we don't have special handlers for SIGCHLD.
61// SA_NODEFER: unimplemented, we can manually change the signal mask appropriately.
62// ~SA_ONSTACK: always silently enable this
63// SA_RESETHAND: unimplemented, but we can probably do this?
64// ~SA_RESTART: unimplemented, maybe we can reserve an RT signal, register an empty handler that
65// doesn't have SA_RESTART, and raise the signal to avoid restarting syscalls that are
66// expected to be interrupted?
Dave Allisonf4b80bc2014-05-14 15:41:25 -070067
Dave Allisonf4b80bc2014-05-14 15:41:25 -070068static void log(const char* format, ...) {
69 char buf[256];
70 va_list ap;
71 va_start(ap, format);
72 vsnprintf(buf, sizeof(buf), format, ap);
Bilyan Borisovbb661c02016-04-04 16:27:32 +010073#ifdef ART_TARGET_ANDROID
Dave Allisonf4b80bc2014-05-14 15:41:25 -070074 __android_log_write(ANDROID_LOG_ERROR, "libsigchain", buf);
Dave Allison69dfe512014-07-11 17:11:58 +000075#else
76 std::cout << buf << "\n";
77#endif
Dave Allisonf4b80bc2014-05-14 15:41:25 -070078 va_end(ap);
79}
80
Josh Gao85a78cf2017-03-20 16:26:42 -070081#define fatal(...) log(__VA_ARGS__); abort()
Josh Gao7600fa92017-03-15 17:40:42 -070082
Josh Gaod32d79d2018-02-26 14:29:25 -080083#if defined(__BIONIC__) && !defined(__LP64__)
84static int sigismember(const sigset64_t* sigset, int signum) {
85 return sigismember64(sigset, signum);
86}
87
88static int sigemptyset(sigset64_t* sigset) {
89 return sigemptyset64(sigset);
90}
91
92static int sigaddset(sigset64_t* sigset, int signum) {
93 return sigaddset64(sigset, signum);
94}
95
96static int sigdelset(sigset64_t* sigset, int signum) {
97 return sigdelset64(sigset, signum);
98}
99#endif
100
101template<typename SigsetType>
102static int sigorset(SigsetType* dest, SigsetType* left, SigsetType* right) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700103 sigemptyset(dest);
Josh Gaod32d79d2018-02-26 14:29:25 -0800104 for (size_t i = 0; i < sizeof(SigsetType) * CHAR_BIT; ++i) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700105 if (sigismember(left, i) == 1 || sigismember(right, i) == 1) {
106 sigaddset(dest, i);
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700107 }
Josh Gao85a78cf2017-03-20 16:26:42 -0700108 }
109 return 0;
110}
111
112namespace art {
113
114static decltype(&sigaction) linked_sigaction;
115static decltype(&sigprocmask) linked_sigprocmask;
Josh Gao99875e92017-04-17 15:58:36 -0700116
Josh Gaod32d79d2018-02-26 14:29:25 -0800117#if defined(__BIONIC__)
118static decltype(&sigaction64) linked_sigaction64;
119static decltype(&sigprocmask64) linked_sigprocmask64;
120#endif
121
122template<typename T>
123static void lookup_next_symbol(T* output, T wrapper, const char* name) {
124 void* sym = dlsym(RTLD_NEXT, name);
125 if (sym == nullptr) {
126 sym = dlsym(RTLD_DEFAULT, name);
127 if (sym == wrapper || sym == sigaction) {
128 fatal("Unable to find next %s in signal chain", name);
129 }
130 }
131 *output = reinterpret_cast<T>(sym);
132}
133
Josh Gaofd4d0d32017-04-26 19:09:47 -0700134__attribute__((constructor)) static void InitializeSignalChain() {
135 static std::once_flag once;
136 std::call_once(once, []() {
Josh Gaod32d79d2018-02-26 14:29:25 -0800137 lookup_next_symbol(&linked_sigaction, sigaction, "sigaction");
138 lookup_next_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask");
Josh Gaofd4d0d32017-04-26 19:09:47 -0700139
Josh Gaod32d79d2018-02-26 14:29:25 -0800140#if defined(__BIONIC__)
141 lookup_next_symbol(&linked_sigaction64, sigaction64, "sigaction64");
142 lookup_next_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64");
143#endif
Josh Gaofd4d0d32017-04-26 19:09:47 -0700144 });
145}
146
Josh Gao99875e92017-04-17 15:58:36 -0700147static pthread_key_t GetHandlingSignalKey() {
148 static pthread_key_t key;
149 static std::once_flag once;
150 std::call_once(once, []() {
151 int rc = pthread_key_create(&key, nullptr);
152 if (rc != 0) {
153 fatal("failed to create sigchain pthread key: %s", strerror(rc));
154 }
155 });
156 return key;
157}
158
159static bool GetHandlingSignal() {
160 void* result = pthread_getspecific(GetHandlingSignalKey());
161 return reinterpret_cast<uintptr_t>(result);
162}
163
164static void SetHandlingSignal(bool value) {
165 pthread_setspecific(GetHandlingSignalKey(),
166 reinterpret_cast<void*>(static_cast<uintptr_t>(value)));
167}
168
169class ScopedHandlingSignal {
170 public:
171 ScopedHandlingSignal() : original_value_(GetHandlingSignal()) {
172 }
173
174 ~ScopedHandlingSignal() {
175 SetHandlingSignal(original_value_);
176 }
177
178 private:
179 bool original_value_;
180};
Josh Gao85a78cf2017-03-20 16:26:42 -0700181
182class SignalChain {
183 public:
184 SignalChain() : claimed_(false) {
Jin Qian33dca562017-03-18 02:51:37 +0000185 }
186
Josh Gao85a78cf2017-03-20 16:26:42 -0700187 bool IsClaimed() {
188 return claimed_;
189 }
190
191 void Claim(int signo) {
192 if (!claimed_) {
193 Register(signo);
194 claimed_ = true;
Jin Qian33dca562017-03-18 02:51:37 +0000195 }
Josh Gao85a78cf2017-03-20 16:26:42 -0700196 }
197
198 // Register the signal chain with the kernel if needed.
199 void Register(int signo) {
Josh Gaod32d79d2018-02-26 14:29:25 -0800200#if defined(__BIONIC__)
201 struct sigaction64 handler_action = {};
202 sigfillset64(&handler_action.sa_mask);
203#else
Josh Gao85a78cf2017-03-20 16:26:42 -0700204 struct sigaction handler_action = {};
Josh Gaod32d79d2018-02-26 14:29:25 -0800205 sigfillset(&handler_action.sa_mask);
206#endif
207
Josh Gao85a78cf2017-03-20 16:26:42 -0700208 handler_action.sa_sigaction = SignalChain::Handler;
209 handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
Josh Gaod32d79d2018-02-26 14:29:25 -0800210
211#if defined(__BIONIC__)
212 linked_sigaction64(signo, &handler_action, &action_);
213#else
Josh Gao85a78cf2017-03-20 16:26:42 -0700214 linked_sigaction(signo, &handler_action, &action_);
Josh Gaod32d79d2018-02-26 14:29:25 -0800215#endif
Josh Gao85a78cf2017-03-20 16:26:42 -0700216 }
217
Josh Gaod32d79d2018-02-26 14:29:25 -0800218 template <typename SigactionType>
219 SigactionType GetAction() {
220 if constexpr (std::is_same_v<decltype(action_), SigactionType>) {
221 return action_;
222 } else {
223 SigactionType result;
224 result.sa_flags = action_.sa_flags;
225 result.sa_handler = action_.sa_handler;
226 result.sa_restorer = action_.sa_restorer;
227 memcpy(&result.sa_mask, &action_.sa_mask,
228 std::min(sizeof(action_.sa_mask), sizeof(result.sa_mask)));
229 return result;
230 }
Josh Gao85a78cf2017-03-20 16:26:42 -0700231 }
232
Josh Gaod32d79d2018-02-26 14:29:25 -0800233 template <typename SigactionType>
234 void SetAction(const SigactionType* new_action) {
235 if constexpr (std::is_same_v<decltype(action_), SigactionType>) {
236 action_ = *new_action;
237 } else {
238 action_.sa_flags = new_action->sa_flags;
239 action_.sa_handler = new_action->sa_handler;
240 action_.sa_restorer = new_action->sa_restorer;
241 sigemptyset(&action_.sa_mask);
242 memcpy(&action_.sa_mask, &new_action->sa_mask,
243 std::min(sizeof(action_.sa_mask), sizeof(new_action->sa_mask)));
244 }
Josh Gao85a78cf2017-03-20 16:26:42 -0700245 }
246
Josh Gao6b2018f2017-05-04 13:55:28 -0700247 void AddSpecialHandler(SigchainAction* sa) {
248 for (SigchainAction& slot : special_handlers_) {
249 if (slot.sc_sigaction == nullptr) {
250 slot = *sa;
Josh Gao85a78cf2017-03-20 16:26:42 -0700251 return;
252 }
253 }
254
255 fatal("too many special signal handlers");
256 }
257
Josh Gao6b2018f2017-05-04 13:55:28 -0700258 void RemoveSpecialHandler(bool (*fn)(int, siginfo_t*, void*)) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700259 // This isn't thread safe, but it's unlikely to be a real problem.
260 size_t len = sizeof(special_handlers_)/sizeof(*special_handlers_);
261 for (size_t i = 0; i < len; ++i) {
Josh Gao6b2018f2017-05-04 13:55:28 -0700262 if (special_handlers_[i].sc_sigaction == fn) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700263 for (size_t j = i; j < len - 1; ++j) {
264 special_handlers_[j] = special_handlers_[j + 1];
265 }
Josh Gao6b2018f2017-05-04 13:55:28 -0700266 special_handlers_[len - 1].sc_sigaction = nullptr;
Josh Gao85a78cf2017-03-20 16:26:42 -0700267 return;
268 }
269 }
270
271 fatal("failed to find special handler to remove");
272 }
273
274
275 static void Handler(int signo, siginfo_t* siginfo, void*);
276
277 private:
278 bool claimed_;
Josh Gaod32d79d2018-02-26 14:29:25 -0800279#if defined(__BIONIC__)
280 struct sigaction64 action_;
281#else
Josh Gao85a78cf2017-03-20 16:26:42 -0700282 struct sigaction action_;
Josh Gaod32d79d2018-02-26 14:29:25 -0800283#endif
Josh Gao6b2018f2017-05-04 13:55:28 -0700284 SigchainAction special_handlers_[2];
Josh Gao85a78cf2017-03-20 16:26:42 -0700285};
286
Josh Gao07d7a5d2018-02-26 14:12:34 -0800287// _NSIG is 1 greater than the highest valued signal, but signals start from 1.
288// Leave an empty element at index 0 for convenience.
289static SignalChain chains[_NSIG + 1];
Josh Gao85a78cf2017-03-20 16:26:42 -0700290
Josh Gao85a78cf2017-03-20 16:26:42 -0700291void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) {
292 // Try the special handlers first.
293 // If one of them crashes, we'll reenter this handler and pass that crash onto the user handler.
Josh Gao99875e92017-04-17 15:58:36 -0700294 if (!GetHandlingSignal()) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700295 for (const auto& handler : chains[signo].special_handlers_) {
Josh Gao6b2018f2017-05-04 13:55:28 -0700296 if (handler.sc_sigaction == nullptr) {
297 break;
298 }
299
300 // The native bridge signal handler might not return.
301 // Avoid setting the thread local flag in this case, since we'll never
302 // get a chance to restore it.
303 bool handler_noreturn = (handler.sc_flags & SIGCHAIN_ALLOW_NORETURN);
304 sigset_t previous_mask;
305 linked_sigprocmask(SIG_SETMASK, &handler.sc_mask, &previous_mask);
306
307 ScopedHandlingSignal restorer;
308 if (!handler_noreturn) {
309 SetHandlingSignal(true);
310 }
311
312 if (handler.sc_sigaction(signo, siginfo, ucontext_raw)) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700313 return;
314 }
Josh Gao6b2018f2017-05-04 13:55:28 -0700315
316 linked_sigprocmask(SIG_SETMASK, &previous_mask, nullptr);
Josh Gao85a78cf2017-03-20 16:26:42 -0700317 }
318 }
319
320 // Forward to the user's signal handler.
321 int handler_flags = chains[signo].action_.sa_flags;
322 ucontext_t* ucontext = static_cast<ucontext_t*>(ucontext_raw);
Josh Gaod32d79d2018-02-26 14:29:25 -0800323#if defined(__BIONIC__)
324 sigset64_t mask;
325 sigorset(&mask, &ucontext->uc_sigmask64, &chains[signo].action_.sa_mask);
326#else
Josh Gao85a78cf2017-03-20 16:26:42 -0700327 sigset_t mask;
328 sigorset(&mask, &ucontext->uc_sigmask, &chains[signo].action_.sa_mask);
Josh Gaod32d79d2018-02-26 14:29:25 -0800329#endif
Josh Gao04de4fe2017-05-31 20:24:51 -0700330 if (!(handler_flags & SA_NODEFER)) {
331 sigaddset(&mask, signo);
Josh Gao85a78cf2017-03-20 16:26:42 -0700332 }
Josh Gaod32d79d2018-02-26 14:29:25 -0800333
334#if defined(__BIONIC__)
335 linked_sigprocmask64(SIG_SETMASK, &mask, nullptr);
336#else
Josh Gao6b2018f2017-05-04 13:55:28 -0700337 linked_sigprocmask(SIG_SETMASK, &mask, nullptr);
Josh Gaod32d79d2018-02-26 14:29:25 -0800338#endif
Josh Gao85a78cf2017-03-20 16:26:42 -0700339
340 if ((handler_flags & SA_SIGINFO)) {
341 chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw);
Jin Qian33dca562017-03-18 02:51:37 +0000342 } else {
Josh Gao85a78cf2017-03-20 16:26:42 -0700343 auto handler = chains[signo].action_.sa_handler;
344 if (handler == SIG_IGN) {
345 return;
346 } else if (handler == SIG_DFL) {
Josh Gaofb539a42017-03-20 16:23:41 -0700347 fatal("exiting due to SIG_DFL handler for signal %d", signo);
Jin Qian33dca562017-03-18 02:51:37 +0000348 } else {
Josh Gao85a78cf2017-03-20 16:26:42 -0700349 handler(signo);
Jin Qian33dca562017-03-18 02:51:37 +0000350 }
351 }
352}
353
Josh Gaod32d79d2018-02-26 14:29:25 -0800354template <typename SigactionType>
355static int __sigaction(int signal, const SigactionType* new_action,
356 SigactionType* old_action,
357 int (*linked)(int, const SigactionType*,
358 SigactionType*)) {
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700359 // If this signal has been claimed as a signal chain, record the user's
360 // action but don't pass it on to the kernel.
361 // Note that we check that the signal number is in range here. An out of range signal
362 // number should behave exactly as the libc sigaction.
Josh Gao07d7a5d2018-02-26 14:12:34 -0800363 if (signal <= 0 || signal >= _NSIG) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700364 errno = EINVAL;
365 return -1;
366 }
367
Josh Gao9d631dd2017-03-23 20:04:58 -0700368 if (chains[signal].IsClaimed()) {
Josh Gaod32d79d2018-02-26 14:29:25 -0800369 SigactionType saved_action = chains[signal].GetAction<SigactionType>();
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700370 if (new_action != nullptr) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700371 chains[signal].SetAction(new_action);
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700372 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700373 if (old_action != nullptr) {
Dmitriy Ivanovc01683b2015-01-06 14:55:26 -0800374 *old_action = saved_action;
375 }
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700376 return 0;
377 }
378
379 // Will only get here if the signal chain has not been claimed. We want
380 // to pass the sigaction on to the kernel via the real sigaction in libc.
Josh Gaod32d79d2018-02-26 14:29:25 -0800381 return linked(signal, new_action, old_action);
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700382}
383
Josh Gaod32d79d2018-02-26 14:29:25 -0800384extern "C" int sigaction(int signal, const struct sigaction* new_action,
385 struct sigaction* old_action) {
386 InitializeSignalChain();
387 return __sigaction(signal, new_action, old_action, linked_sigaction);
388}
389
390#if defined(__BIONIC__)
391extern "C" int sigaction64(int signal, const struct sigaction64* new_action,
392 struct sigaction64* old_action) {
393 InitializeSignalChain();
394 return __sigaction(signal, new_action, old_action, linked_sigaction64);
395}
396#endif
397
Josh Gao85a78cf2017-03-20 16:26:42 -0700398extern "C" sighandler_t signal(int signo, sighandler_t handler) {
Josh Gaofd4d0d32017-04-26 19:09:47 -0700399 InitializeSignalChain();
400
Josh Gao07d7a5d2018-02-26 14:12:34 -0800401 if (signo <= 0 || signo >= _NSIG) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700402 errno = EINVAL;
403 return SIG_ERR;
404 }
405
406 struct sigaction sa = {};
Dave Allison91a83662014-08-28 16:12:40 -0700407 sigemptyset(&sa.sa_mask);
408 sa.sa_handler = handler;
Josh Gao85a78cf2017-03-20 16:26:42 -0700409 sa.sa_flags = SA_RESTART | SA_ONSTACK;
Dave Allison91a83662014-08-28 16:12:40 -0700410 sighandler_t oldhandler;
411
412 // If this signal has been claimed as a signal chain, record the user's
413 // action but don't pass it on to the kernel.
Josh Gao85a78cf2017-03-20 16:26:42 -0700414 if (chains[signo].IsClaimed()) {
Josh Gaod32d79d2018-02-26 14:29:25 -0800415 oldhandler = reinterpret_cast<sighandler_t>(
416 chains[signo].GetAction<struct sigaction>().sa_handler);
Josh Gao85a78cf2017-03-20 16:26:42 -0700417 chains[signo].SetAction(&sa);
Dave Allison91a83662014-08-28 16:12:40 -0700418 return oldhandler;
419 }
420
421 // Will only get here if the signal chain has not been claimed. We want
422 // to pass the sigaction on to the kernel via the real sigaction in libc.
Josh Gao85a78cf2017-03-20 16:26:42 -0700423 if (linked_sigaction(signo, &sa, &sa) == -1) {
Dave Allison91a83662014-08-28 16:12:40 -0700424 return SIG_ERR;
425 }
426
427 return reinterpret_cast<sighandler_t>(sa.sa_handler);
428}
429
Dimitry Ivanov82b67b92016-08-01 11:19:03 -0700430#if !defined(__LP64__)
Josh Gao85a78cf2017-03-20 16:26:42 -0700431extern "C" sighandler_t bsd_signal(int signo, sighandler_t handler) {
Josh Gaofd4d0d32017-04-26 19:09:47 -0700432 InitializeSignalChain();
433
Josh Gao85a78cf2017-03-20 16:26:42 -0700434 return signal(signo, handler);
Dimitry Ivanov82b67b92016-08-01 11:19:03 -0700435}
436#endif
437
Josh Gaod32d79d2018-02-26 14:29:25 -0800438template <typename SigsetType>
439int __sigprocmask(int how, const SigsetType* new_set, SigsetType* old_set,
440 int (*linked)(int, const SigsetType*, SigsetType*)) {
Josh Gao90444552017-03-20 14:58:25 -0700441 // When inside a signal handler, forward directly to the actual sigprocmask.
Josh Gao99875e92017-04-17 15:58:36 -0700442 if (GetHandlingSignal()) {
Josh Gaod32d79d2018-02-26 14:29:25 -0800443 return linked(how, new_set, old_set);
Josh Gao90444552017-03-20 14:58:25 -0700444 }
445
Josh Gaod32d79d2018-02-26 14:29:25 -0800446 const SigsetType* new_set_ptr = new_set;
447 SigsetType tmpset;
448 if (new_set != nullptr) {
449 tmpset = *new_set;
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700450
Josh Gaof74caac2018-02-26 14:13:52 -0800451 if (how == SIG_BLOCK || how == SIG_SETMASK) {
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700452 // Don't allow claimed signals in the mask. If a signal chain has been claimed
453 // we can't allow the user to block that signal.
Josh Gao07d7a5d2018-02-26 14:12:34 -0800454 for (int i = 1; i < _NSIG; ++i) {
Josh Gao85a78cf2017-03-20 16:26:42 -0700455 if (chains[i].IsClaimed() && sigismember(&tmpset, i)) {
Dmitriy Ivanova3164b92015-04-01 11:08:45 -0700456 sigdelset(&tmpset, i);
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700457 }
458 }
459 }
460 new_set_ptr = &tmpset;
461 }
462
Josh Gaod32d79d2018-02-26 14:29:25 -0800463 return linked(how, new_set_ptr, old_set);
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700464}
Dave Allisoncefcea82014-09-16 10:01:01 -0700465
Josh Gaod32d79d2018-02-26 14:29:25 -0800466extern "C" int sigprocmask(int how, const sigset_t* new_set,
467 sigset_t* old_set) {
468 InitializeSignalChain();
469 return __sigprocmask(how, new_set, old_set, linked_sigprocmask);
470}
471
472#if defined(__BIONIC__)
473extern "C" int sigprocmask64(int how, const sigset64_t* new_set,
474 sigset64_t* old_set) {
475 InitializeSignalChain();
476 return __sigprocmask(how, new_set, old_set, linked_sigprocmask64);
477}
478#endif
479
Josh Gao6b2018f2017-05-04 13:55:28 -0700480extern "C" void AddSpecialSignalHandlerFn(int signal, SigchainAction* sa) {
Josh Gaofd4d0d32017-04-26 19:09:47 -0700481 InitializeSignalChain();
482
Josh Gao85a78cf2017-03-20 16:26:42 -0700483 if (signal <= 0 || signal >= _NSIG) {
484 fatal("Invalid signal %d", signal);
485 }
Andreas Gampe03c2cc82015-05-22 18:31:50 -0700486
487 // Set the managed_handler.
Josh Gao6b2018f2017-05-04 13:55:28 -0700488 chains[signal].AddSpecialHandler(sa);
Josh Gao85a78cf2017-03-20 16:26:42 -0700489 chains[signal].Claim(signal);
490}
Andreas Gampe03c2cc82015-05-22 18:31:50 -0700491
Josh Gao6b2018f2017-05-04 13:55:28 -0700492extern "C" void RemoveSpecialSignalHandlerFn(int signal, bool (*fn)(int, siginfo_t*, void*)) {
Josh Gaofd4d0d32017-04-26 19:09:47 -0700493 InitializeSignalChain();
494
Josh Gao85a78cf2017-03-20 16:26:42 -0700495 if (signal <= 0 || signal >= _NSIG) {
496 fatal("Invalid signal %d", signal);
497 }
498
499 chains[signal].RemoveSpecialHandler(fn);
500}
501
502extern "C" void EnsureFrontOfChain(int signal) {
Josh Gaofd4d0d32017-04-26 19:09:47 -0700503 InitializeSignalChain();
504
Josh Gao85a78cf2017-03-20 16:26:42 -0700505 if (signal <= 0 || signal >= _NSIG) {
506 fatal("Invalid signal %d", signal);
507 }
508
509 // Read the current action without looking at the chain, it should be the expected action.
510 struct sigaction current_action;
Josh Gao85a78cf2017-03-20 16:26:42 -0700511 linked_sigaction(signal, nullptr, &current_action);
Josh Gaofd4d0d32017-04-26 19:09:47 -0700512
Josh Gao85a78cf2017-03-20 16:26:42 -0700513 // If the sigactions don't match then we put the current action on the chain and make ourself as
514 // the main action.
515 if (current_action.sa_sigaction != SignalChain::Handler) {
516 log("Warning: Unexpected sigaction action found %p\n", current_action.sa_sigaction);
517 chains[signal].Register(signal);
Andreas Gampe03c2cc82015-05-22 18:31:50 -0700518 }
519}
520
Dave Allisonf4b80bc2014-05-14 15:41:25 -0700521} // namespace art
522