1 /*
2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
4 */
5 #include "cmogstored.h"
6
7 /*
8 * we block signals in pool threads, only the main thread receives signals
9 */
10
11 static sigset_t fullset;
12 sigset_t mog_emptyset;
13
sig_init(void)14 __attribute__((constructor)) static void sig_init(void)
15 {
16 CHECK(int, 0, sigfillset(&fullset));
17 CHECK(int, 0, sigemptyset(&mog_emptyset));
18 }
19
mog_intr_disable(void)20 void mog_intr_disable(void)
21 {
22 CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &fullset, NULL));
23 }
24
mog_intr_enable(void)25 void mog_intr_enable(void)
26 {
27 CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &mog_emptyset, NULL));
28 }
29
sleeper(struct timespec * tsp,const sigset_t * sigmask)30 static int sleeper(struct timespec *tsp, const sigset_t *sigmask)
31 {
32 int err = 0;
33
34 /*
35 * pselect is a cancellation point,
36 * ppoll is not POSIX and is only a cancellation point on glibc.
37 */
38 if (pselect(0, NULL, NULL, NULL, tsp, sigmask) < 0) {
39 err = errno;
40 assert((err == EINTR || err == ENOMEM) &&
41 "BUG in pselect usage");
42 }
43 return err;
44 }
45
46 /* thread-safe, interruptible sleep, negative seconds -> sleep forever */
mog_sleep(long seconds)47 int mog_sleep(long seconds)
48 {
49 struct timespec ts;
50 struct timespec *tsp;
51
52 if (seconds < 0) {
53 tsp = NULL;
54 } else {
55 ts.tv_sec = seconds;
56 ts.tv_nsec = 0;
57 tsp = &ts;
58 }
59
60 return sleeper(tsp, &mog_emptyset);
61 }
62