blob: 9a23416048884c26028fea051bf0cbdec28483c6 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
Elliott Hughesc7e9b232013-10-16 22:27:54 -070028
Elliott Hughes6dafb4a2018-01-26 17:47:56 -080029#include <errno.h>
30#include <pthread.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080031#include <signal.h>
Elliott Hughes6dafb4a2018-01-26 17:47:56 -080032#include <string.h>
33#include <sys/types.h>
34#include <time.h>
35#include <unistd.h>
36
37#include "private/kernel_sigset_t.h"
38
39extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
40extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
41
42int sigaddset(sigset_t* set, int signum) {
43 int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
44 unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
45 if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
46 errno = EINVAL;
47 return -1;
48 }
49 local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
50 return 0;
51}
52
53// This isn't in our header files, but is exposed on all architectures.
54extern "C" int sigblock(int mask) {
55 union {
56 int mask;
57 sigset_t set;
58 } in, out;
59
60 sigemptyset(&in.set);
61 in.mask = mask;
62
63 if (sigprocmask(SIG_BLOCK, &in.set, &out.set) == -1) return -1;
64 return out.mask;
65}
66
67int sigdelset(sigset_t* set, int signum) {
68 int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
69 unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
70 if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
71 errno = EINVAL;
72 return -1;
73 }
74 local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
75 return 0;
76}
77
78int sigemptyset(sigset_t* set) {
79 if (set == NULL) {
80 errno = EINVAL;
81 return -1;
82 }
83 memset(set, 0, sizeof(sigset_t));
84 return 0;
85}
86
87int sigfillset(sigset_t* set) {
88 if (set == NULL) {
89 errno = EINVAL;
90 return -1;
91 }
92 memset(set, ~0, sizeof(sigset_t));
93 return 0;
94}
95
96int sighold(int sig) {
97 kernel_sigset_t set;
98 set.clear();
99 if (!set.set(sig)) return -1;
100 return __rt_sigprocmask(SIG_BLOCK, &set, nullptr, sizeof(set));
101}
102
103int sigignore(int sig) {
104 struct sigaction sa;
105 memset(&sa, 0, sizeof(sa));
106 if (sigemptyset(&sa.sa_mask) == -1) return -1;
107 sa.sa_handler = SIG_IGN;
108 return sigaction(sig, &sa, nullptr);
109}
110
111int siginterrupt(int sig, int flag) {
112 struct sigaction act;
113 sigaction(sig, nullptr, &act);
114 if (flag) {
115 act.sa_flags &= ~SA_RESTART;
116 } else {
117 act.sa_flags |= SA_RESTART;
118 }
119 return sigaction(sig, &act, nullptr);
120}
121
122int sigismember(const sigset_t* set, int signum) {
123 int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
124 const unsigned long* local_set = reinterpret_cast<const unsigned long*>(set);
125 if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
126 errno = EINVAL;
127 return -1;
128 }
129 return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
130}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800131
Christopher Ferris1721cd62015-10-30 17:10:47 -0700132__LIBC_HIDDEN__ sighandler_t _signal(int signum, sighandler_t handler, int flags) {
Elliott Hughesc7e9b232013-10-16 22:27:54 -0700133 struct sigaction sa;
134 sigemptyset(&sa.sa_mask);
135 sa.sa_handler = handler;
136 sa.sa_flags = flags;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800137
Elliott Hughesc7e9b232013-10-16 22:27:54 -0700138 if (sigaction(signum, &sa, &sa) == -1) {
139 return SIG_ERR;
140 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800141
Elliott Hughes8b5df392015-01-21 16:19:07 -0800142 return sa.sa_handler;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800143}
144
Elliott Hughesc7e9b232013-10-16 22:27:54 -0700145sighandler_t signal(int signum, sighandler_t handler) {
Dan Albert205dd7d2014-06-04 10:14:19 -0700146 return _signal(signum, handler, SA_RESTART);
Elliott Hughesc7e9b232013-10-16 22:27:54 -0700147}
Elliott Hughes6dafb4a2018-01-26 17:47:56 -0800148
149int sigpause(int sig) {
150 kernel_sigset_t set;
151 set.clear();
152 if (__rt_sigprocmask(SIG_SETMASK, nullptr, &set, sizeof(set)) == -1) return -1;
153 if (!set.clear(sig)) return -1;
154 return __rt_sigsuspend(&set, sizeof(set));
155}
156
157int sigpending(sigset_t* bionic_set) {
158 kernel_sigset_t set;
159 int result = __rt_sigpending(&set, sizeof(set));
160 if (result != -1) {
161 *bionic_set = set.bionic;
162 }
163 return result;
164}
165
166int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
167 kernel_sigset_t new_set;
168 kernel_sigset_t* new_set_ptr = NULL;
169 if (bionic_new_set != NULL) {
170 new_set.set(bionic_new_set);
171 new_set_ptr = &new_set;
172 }
173
174 kernel_sigset_t old_set;
175 if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) {
176 return -1;
177 }
178
179 if (bionic_old_set != NULL) {
180 *bionic_old_set = old_set.bionic;
181 }
182
183 return 0;
184}
185
186int sigqueue(pid_t pid, int signo, const sigval value) {
187 siginfo_t info;
188 memset(&info, 0, sizeof(siginfo_t));
189 info.si_signo = signo;
190 info.si_code = SI_QUEUE;
191 info.si_pid = getpid();
192 info.si_uid = getuid();
193 info.si_value = value;
194
195 return ___rt_sigqueueinfo(pid, signo, &info);
196}
197
198int sigrelse(int sig) {
199 kernel_sigset_t set;
200 set.clear();
201 if (!set.set(sig)) return -1;
202 return __rt_sigprocmask(SIG_UNBLOCK, &set, nullptr, sizeof(set));
203}
204
205sighandler_t sigset(int sig, sighandler_t disp) {
206 struct sigaction new_sa;
207 if (disp != SIG_HOLD) {
208 memset(&new_sa, 0, sizeof(new_sa));
209 new_sa.sa_handler = disp;
210 sigemptyset(&new_sa.sa_mask);
211 }
212
213 struct sigaction old_sa;
214 if (sigaction(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
215 return SIG_ERR;
216 }
217
218 kernel_sigset_t new_mask{sig};
219 kernel_sigset_t old_mask;
220 if (__rt_sigprocmask(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask,
221 sizeof(new_mask)) == -1) {
222 return SIG_ERR;
223 }
224
225 return old_mask.is_set(sig) ? SIG_HOLD : old_sa.sa_handler;
226}
227
228// This isn't in our header files, but is exposed on all architectures.
229extern "C" int sigsetmask(int mask) {
230 union {
231 int mask;
232 sigset_t set;
233 } in, out;
234
235 sigemptyset(&in.set);
236 in.mask = mask;
237
238 if (sigprocmask(SIG_SETMASK, &in.set, &out.set) == -1) return -1;
239 return out.mask;
240}
241
242int sigsuspend(const sigset_t* bionic_set) {
243 kernel_sigset_t set(bionic_set);
244 return __rt_sigsuspend(&set, sizeof(set));
245}
246
247int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
248 kernel_sigset_t sigset(set);
249 return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset));
250}
251
252int sigwait(const sigset_t* set, int* sig) {
253 kernel_sigset_t sigset(set);
254 while (true) {
255 // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
256 // around them since sigwait is only allowed to return EINVAL.
257 int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset));
258 if (result >= 0) {
259 *sig = result;
260 return 0;
261 }
262
263 if (errno != EAGAIN && errno != EINTR) {
264 return errno;
265 }
266 }
267}
268
269int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
270 return sigtimedwait(set, info, NULL);
271}