• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <sigchain.h>
17 #include <locale.h>
18 #include <pthread.h>
19 #include <errno.h>
20 #include <threads.h>
21 #include <musl_log.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <pthread_impl.h>
25 #include "malloc.h"
26 #include "syscall.h"
27 
28 extern int __libc_sigaction(int sig, const struct sigaction *restrict sa,
29                             struct sigaction *restrict old);
30 
31 #define SIG_CHAIN_KEY_VALUE_1 1
32 #define SIGNAL_CHAIN_SPECIAL_ACTION_MAX 3
33 
34 #define SIGCHAIN_LOG_TAG "MUSL-SIGCHAIN"
35 
36 #if (defined(OHOS_ENABLE_PARAMETER) || defined(ENABLE_MUSL_LOG))
37 #define SIGCHAIN_PRINT_ERROR(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_ERROR, \
38     MUSL_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
39 #define SIGCHAIN_PRINT_INFO(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_INFO, \
40     MUSL_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
41 #define SIGCHAIN_PRINT_DEBUG(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_DEBUG, \
42     MUSL_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
43 #define SIGCHAIN_LOG_FATAL(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_FATAL, \
44     MUSL_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
45 #else
46 #define SIGCHAIN_PRINT_ERROR(...)
47 #define SIGCHAIN_PRINT_INFO(...)
48 #define SIGCHAIN_PRINT_DEBUG(...)
49 #define SIGCHAIN_LOG_FATAL(...)
50 #endif
51 
52 #define FREEZE_SIGNAL_35 (35)
53 #define FREEZE_SIGNAL_38 (38)
54 
55 #define SIGCHAIN_PRINT_FATAL(...)  do {                    \
56     SIGCHAIN_LOG_FATAL(__VA_ARGS__);                      \
57     abort();                                               \
58 } while (0)
59 
60 struct sc_signal_chain {
61     bool marked;
62     struct sigaction sig_action;
63     struct signal_chain_action sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX];
64 };
65 
66 /* Signal chain set, from 0 to 63. */
67 static struct sc_signal_chain sig_chains[_NSIG - 1];
68 /* static thread Keyword */
69 static pthread_key_t g_sigchain_key;
70 /* This is once flag! */
71 static once_flag g_flag = ONCE_FLAG_INIT;
72 
73 /**
74   * @brief Create the thread key
75   * @retval void
76   */
create_pthread_key(void)77 static void create_pthread_key(void)
78 {
79     SIGCHAIN_PRINT_INFO("%{public}s create the thread key!", __func__);
80     int rc = pthread_key_create(&g_sigchain_key, NULL);
81     if (rc != 0) {
82         SIGCHAIN_PRINT_FATAL("%{public}s failed to create sigchain pthread key, rc:%{public}d errno:%{public}d",
83                 __func__,  rc, errno);
84     }
85 }
86 
87 /**
88   * @brief Get the key of the signal thread.
89   * @retval int32_t, the value of the sigchain key.
90   */
get_handling_signal_key()91 static pthread_key_t get_handling_signal_key()
92 {
93     return g_sigchain_key;
94 }
95 
96 /**
97   * @brief Get the value of the sigchain key
98   * @retval bool, true if set the value of the key,or false.
99   */
get_handling_signal()100 static bool get_handling_signal()
101 {
102     void *result = pthread_getspecific(get_handling_signal_key());
103     return result == NULL ? false : true;
104 }
105 
106 /**
107   * @brief Set the value of the sigchain key
108   * @param[in] value, the value of the sigchain key
109   * @retval void.
110   */
set_handling_signal(bool value)111 static void set_handling_signal(bool value)
112 {
113     pthread_setspecific(get_handling_signal_key(),
114                         (void *)((uintptr_t)(value)));
115 }
116 
117 /**
118   * @brief Set the mask of the system. Its prototype comes from pthread_sigmask.
119   * @param[in] how, the value of the mask operation .
120   * @param[in] set, the new value of the sigset.
121   * @param[in] old, the old value of the sigset.
122   */
sigchain_sigmask(int how,const sigset_t * restrict set,sigset_t * restrict old)123 static int sigchain_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict old)
124 {
125     int ret;
126     if (set && (unsigned)how - SIG_BLOCK > 2U) return EINVAL;
127     ret = -__syscall(SYS_rt_sigprocmask, how, set, old, _NSIG/8);
128     if (!ret && old) {
129         if (sizeof old->__bits[0] == 8) {
130             old->__bits[0] &= ~0x380000000ULL;
131         } else {
132             old->__bits[0] &= ~0x80000000UL;
133             old->__bits[1] &= ~0x3UL;
134         }
135     }
136     return ret;
137 }
138 
139 /**
140   * @brief Judge whether the signal is marked
141   * @param[in] signo, the value of the signal.
142   * @retval true if the signal is marked, or false.
143   */
ismarked(int signo)144 static bool ismarked(int signo)
145 {
146     return sig_chains[signo - 1].marked;
147 }
148 
149 #ifdef USE_JEMALLOC_DFX_INTF
150 /**
151   * @brief This is a print function for malloc_stats_print.
152   * @param[in] fp, file descriptor for print.
153   * @param[in] str, string to print.
154   * @retval void
155   */
binlock_print(void * fp,const char * str)156 static void binlock_print(void *fp, const char *str)
157 {
158     SIGCHAIN_PRINT_ERROR("%{public}s", str);
159 }
160 #endif
161 
162 /**
163   * @brief This is a callback function, which is registered to the kernel
164   * @param[in] signo, the value of the signal.
165   * @param[in] siginfo, the information of the signal.
166   * @param[in] ucontext_raw, the context of the signal.
167   * @retval void
168   */
signal_chain_handler(int signo,siginfo_t * siginfo,void * ucontext_raw)169 static void signal_chain_handler(int signo, siginfo_t* siginfo, void* ucontext_raw)
170 {
171     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
172     /* First call special handler. */
173     /* If a process crashes, the sigchain'll call the corresponding  handler */
174     if (!get_handling_signal()) {
175         int idx, validSigaction = 0;
176         for (idx = 0; idx < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; idx++) {
177             if (sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction == NULL) {
178                 continue;
179             }
180             validSigaction = 1;
181             /* The special handler might not return. */
182             bool noreturn = (sig_chains[signo - 1].sca_special_actions[idx].sca_flags &
183                              SIGCHAIN_ALLOW_NORETURN);
184             sigset_t previous_mask;
185             sigchain_sigmask(SIG_SETMASK, &sig_chains[signo - 1].sca_special_actions[idx].sca_mask,
186                             &previous_mask);
187 
188             bool previous_value = get_handling_signal();
189             if (!noreturn) {
190                 set_handling_signal(true);
191             }
192             int thread_list_lock_status = -1;
193             if (signo == FREEZE_SIGNAL_35) {
194 #ifdef a_ll
195                 thread_list_lock_status = a_ll(&__thread_list_lock);
196 #else
197                 thread_list_lock_status = __thread_list_lock;
198 #endif
199 #ifdef USE_JEMALLOC_DFX_INTF
200                 malloc_stats_print(binlock_print, NULL, "o");
201 #endif //USE_JEMALLOC_DFX_INTF
202             } else if (signo == FREEZE_SIGNAL_38) {
203 #ifdef USE_JEMALLOC_DFX_INTF
204                 malloc_stats_print(binlock_print, NULL, "o");
205 #endif
206             }
207               /**
208               * modify style: move `thread_list_lock_status` from `if`
209               * internal branch to outer branch.
210               * void performance degradation
211               */
212             struct call_tl_lock *call_tl_lock_dump;
213             struct call_tl_lock call_tl_lock_stub = { -1 };
214             if (get_tl_lock_caller_count()) {
215                 call_tl_lock_dump = get_tl_lock_caller_count();
216             } else {
217                 call_tl_lock_dump = &call_tl_lock_stub;
218             }
219             SIGCHAIN_PRINT_ERROR("%{public}s call %{public}d rd sigchain action for signal: %{public}d"
220                 " sca_sigaction=%{public}llx noreturn=%{public}d "
221                 "FREEZE_signo_%{public}d thread_list_lock_status:%{public}d "
222                 "tl_lock_count=%{public}d tl_lock_waiters=%{public}d "
223                 "tl_lock_tid_fail=%{public}d tl_lock_count_tid=%{public}d "
224                 "tl_lock_count_fail=%{public}d tl_lock_count_tid_sub=%{public}d "
225                 "thread_list_lock_after_lock=%{public}d thread_list_lock_pre_unlock=%{public}d "
226                 "thread_list_lock_pthread_exit=%{public}d thread_list_lock_tid_overlimit=%{public}d "
227                 "tl_lock_unlock_count=%{public}d "
228                 "__pthread_gettid_np_tl_lock=%{public}d "
229                 "__pthread_exit_tl_lock=%{public}d "
230                 "__pthread_create_tl_lock=%{public}d "
231                 "__pthread_key_delete_tl_lock=%{public}d "
232                 "__synccall_tl_lock=%{public}d "
233                 "__membarrier_tl_lock=%{public}d "
234                 "install_new_tls_tl_lock=%{public}d "
235                 "set_syscall_hooks_tl_lock=%{public}d "
236                 "set_syscall_hooks_linux_tl_lock=%{public}d "
237                 "fork_tl_lock=%{public}d ",
238                 __func__, idx, signo, (unsigned long long)sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction,
239                 noreturn, signo, thread_list_lock_status,
240                 get_tl_lock_count(), get_tl_lock_waiters(), get_tl_lock_tid_fail(), get_tl_lock_count_tid(),
241                 get_tl_lock_count_fail(), get_tl_lock_count_tid_sub(),
242                 get_thread_list_lock_after_lock(), get_thread_list_lock_pre_unlock(),
243                 get_thread_list_lock_pthread_exit(), get_thread_list_lock_tid_overlimit(),
244                 call_tl_lock_dump->tl_lock_unlock_count,
245                 call_tl_lock_dump->__pthread_gettid_np_tl_lock,
246                 call_tl_lock_dump->__pthread_exit_tl_lock,
247                 call_tl_lock_dump->__pthread_create_tl_lock,
248                 call_tl_lock_dump->__pthread_key_delete_tl_lock,
249                 call_tl_lock_dump->__synccall_tl_lock,
250                 call_tl_lock_dump->__membarrier_tl_lock,
251                 call_tl_lock_dump->install_new_tls_tl_lock,
252                 call_tl_lock_dump->set_syscall_hooks_tl_lock,
253                 call_tl_lock_dump->set_syscall_hooks_linux_tl_lock,
254                 call_tl_lock_dump->fork_tl_lock);
255             if (sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction(signo,
256                                                             siginfo, ucontext_raw)) {
257                 set_handling_signal(previous_value);
258                 SIGCHAIN_PRINT_ERROR("%{public}s call %{public}d rd sigchain action for signal: %{public}d directly return", __func__, idx, signo);
259                 return;
260             }
261 
262             sigchain_sigmask(SIG_SETMASK, &previous_mask, NULL);
263             set_handling_signal(previous_value);
264         }
265         if (idx == SIGNAL_CHAIN_SPECIAL_ACTION_MAX && !validSigaction) {
266             SIGCHAIN_PRINT_ERROR("signal_chain_handler sca_sigaction all null for signal: %{public}d", signo);
267         }
268     }
269     /* Then Call the user's signal handler */
270     int sa_flags = sig_chains[signo - 1].sig_action.sa_flags;
271     ucontext_t* ucontext = (ucontext_t*)(ucontext_raw);
272 
273     sigset_t mask;
274     sigorset(&mask, &ucontext->uc_sigmask, &sig_chains[signo - 1].sig_action.sa_mask);
275 
276     if (!(sa_flags & SA_NODEFER)) {
277         sigaddset(&mask, signo);
278     }
279 
280     sigchain_sigmask(SIG_SETMASK, &mask, NULL);
281 
282     if ((sa_flags & SA_SIGINFO)) {
283         SIGCHAIN_PRINT_ERROR("%{public}s call usr sigaction for signal: %{public}d sig_action.sa_sigaction=%{public}llx",
284             __func__, signo, (unsigned long long)sig_chains[signo - 1].sig_action.sa_sigaction);
285         sig_chains[signo - 1].sig_action.sa_sigaction(signo, siginfo, ucontext_raw);
286     } else {
287         if (sig_chains[signo - 1].sig_action.sa_handler == SIG_IGN) {
288             SIGCHAIN_PRINT_ERROR("%{public}s SIG_IGN handler for signal: %{public}d", __func__, signo);
289             return;
290         } else if (sig_chains[signo - 1].sig_action.sa_handler == SIG_DFL) {
291             SIGCHAIN_PRINT_ERROR("%{public}s SIG_DFL handler for signal: %{public}d", __func__, signo);
292             remove_all_special_handler(signo);
293             if (__syscall(SYS_rt_tgsigqueueinfo, __syscall(SYS_getpid), __syscall(SYS_gettid), signo, siginfo) != 0) {
294                 SIGCHAIN_PRINT_ERROR("Failed to rethrow sig(%{public}d), errno(%{public}d).", signo, errno);
295             } else {
296                 SIGCHAIN_PRINT_ERROR("pid(%{public}ld) rethrow sig(%{public}d) success.", __syscall(SYS_getpid), signo);
297             }
298         } else {
299             SIGCHAIN_PRINT_ERROR("%{public}s call usr sa_handler: %{public}llx for signal: %{public}d",
300                 __func__, (unsigned long long)sig_chains[signo - 1].sig_action.sa_handler, signo);
301             sig_chains[signo - 1].sig_action.sa_handler(signo);
302         }
303     }
304 
305     return;
306 }
307 
308 /**
309   * @brief Register the signal chain with the kernel if needed
310   * @param[in] signo, the value of the signal.
311   * @retval void
312   */
sigchain_register(int signo)313 static void sigchain_register(int signo)
314 {
315     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
316     struct sigaction signal_action = {};
317     sigfillset(&signal_action.sa_mask);
318     call_once(&g_flag, create_pthread_key);
319 
320     signal_action.sa_sigaction = signal_chain_handler;
321     signal_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
322     __libc_sigaction(signo, &signal_action, &sig_chains[signo - 1].sig_action);
323 }
324 
325 /**
326   * @brief Unregister the signal from sigchain, register the signal's user handler with the kernel if needed
327   * @param[in] signo, the value of the signal.
328   * @retval void
329   */
unregister_sigchain(int signo)330 static void unregister_sigchain(int signo)
331 {
332     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
333     __libc_sigaction(signo, &sig_chains[signo - 1].sig_action, NULL);
334     sig_chains[signo - 1].marked = false;
335 }
336 
337 /**
338   * @brief Mark the signal to the sigchain.
339   * @param[in] signo, the value of the signal.
340   * @retval void
341   */
mark_signal_to_sigchain(int signo)342 static void mark_signal_to_sigchain(int signo)
343 {
344     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
345     if (!sig_chains[signo - 1].marked) {
346         sigchain_register(signo);
347         sig_chains[signo - 1].marked = true;
348     }
349 }
350 
351 /**
352   * @brief Set the action of the signal.
353   * @param[in] signo, the value of the signal.
354   * @param[in] new_sa, the new action of the signal.
355   * @retval void
356   */
setaction(int signo,const struct sigaction * restrict new_sa)357 static void setaction(int signo, const struct sigaction *restrict new_sa)
358 {
359     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
360     sig_chains[signo - 1].sig_action = *new_sa;
361 }
362 
363 /**
364   * @brief Get the action of the signal.
365   * @param[in] signo, the value of the signal.
366   * @retval The current action of the signal
367   */
getaction(int signo)368 static struct sigaction getaction(int signo)
369 {
370     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
371     return sig_chains[signo - 1].sig_action;
372 }
373 
374 /**
375   * @brief Add the special handler to the sigchain.
376   * @param[in] signo, the value of the signal.
377   * @param[in] sa, the action with special handler.
378   * @retval void
379   */
add_special_handler(int signo,struct signal_chain_action * sa)380 static void add_special_handler(int signo, struct signal_chain_action* sa)
381 {
382     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
383     for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) {
384         if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == NULL) {
385             sig_chains[signo - 1].sca_special_actions[i] = *sa;
386             SIGCHAIN_PRINT_INFO("%{public}s signo %{public}d is registered with special handler!", __func__, signo);
387             return;
388         }
389     }
390 
391     SIGCHAIN_PRINT_FATAL("Add too many the special handlers!");
392 }
393 
394 /**
395   * @brief Remove the special handler from the sigchain.
396   * @param[in] signo, the value of the signal.
397   * @param[in] fn, the special handler of the signal.
398   * @retval void
399   */
rm_special_handler(int signo,bool (* fn)(int,siginfo_t *,void *))400 static void rm_special_handler(int signo, bool (*fn)(int, siginfo_t*, void*))
401 {
402     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
403     int len = SIGNAL_CHAIN_SPECIAL_ACTION_MAX;
404     for (int i = 0; i < len; i++) {
405         if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == fn) {
406             sig_chains[signo - 1].sca_special_actions[i].sca_sigaction = NULL;
407             int count = 0;
408             for (int k = 0; k < len; k++) {
409                 if (sig_chains[signo - 1].sca_special_actions[k].sca_sigaction == NULL) {
410                     count++;
411                 }
412             }
413             if (count == len) {
414                 unregister_sigchain(signo);
415             }
416             return;
417         }
418     }
419 
420     SIGCHAIN_PRINT_FATAL("%{public}s failed to remove the special handler!. signo: %{public}d",
421             __func__, signo);
422 }
423 
424 /**
425   * @brief This is an external interface,
426   *        Mark the signal to sigchain ,add the special handler to the sigchain.
427   * @param[in] signo, the value of the signal.
428   * @param[in] sa, the action with special handler.
429   * @retval void
430   */
add_special_signal_handler(int signo,struct signal_chain_action * sa)431 void add_special_signal_handler(int signo, struct signal_chain_action* sa)
432 {
433     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
434     if (signo <= 0 || signo >= _NSIG) {
435         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
436         return;
437     }
438 
439     // Add the special hander to the sigchain
440     add_special_handler(signo, sa);
441     mark_signal_to_sigchain(signo);
442 }
443 
444 /**
445   * @brief This is an external interface, remove the special handler from the sigchain.
446   * @param[in] signo, the value of the signal.
447   * @param[in] fn, the special handler of the signal.
448   * @retval void
449   */
remove_special_signal_handler(int signo,bool (* fn)(int,siginfo_t *,void *))450 void remove_special_signal_handler(int signo, bool (*fn)(int, siginfo_t*, void*))
451 {
452     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
453     if (signo <= 0 || signo >= _NSIG) {
454         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
455         return;
456     }
457 
458     if (ismarked(signo)) {
459         // remove the special handler from the sigchain.
460         rm_special_handler(signo, fn);
461     }
462 }
463 
464 /**
465   * @brief This is an external interface, remove all special handler from the sigchain.
466   * @param[in] signo, the value of the signal.
467   * @retval void
468   */
remove_all_special_handler(int signo)469 void remove_all_special_handler(int signo)
470 {
471     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
472     if (signo <= 0 || signo >= _NSIG) {
473         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
474         return;
475     }
476 
477     if (ismarked(signo)) {
478         // remove all special handler from the sigchain.
479         for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) {
480             sig_chains[signo - 1].sca_special_actions[i].sca_sigaction = NULL;
481         }
482         unregister_sigchain(signo);
483     }
484 }
485 
486 /**
487   * @brief This is an external interface, add the special handler at the last of sigchain chains.
488   * @param[in] signo, the value of the signal.
489   * @param[in] sa, the action with special handler.
490   * @retval void
491   */
add_special_handler_at_last(int signo,struct signal_chain_action * sa)492 void add_special_handler_at_last(int signo, struct signal_chain_action* sa)
493 {
494     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
495     if (signo <= 0 || signo >= _NSIG) {
496         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
497         return;
498     }
499 
500     if (sig_chains[signo - 1].sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX - 1].sca_sigaction == NULL) {
501         sig_chains[signo - 1].sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX - 1] = *sa;
502         mark_signal_to_sigchain(signo);
503         return;
504     }
505 
506     SIGCHAIN_PRINT_FATAL("Add too many the special handlers at last!");
507 }
508 
509 /**
510   * @brief Intercept the signal and sigaction.
511   * @param[in] signo, the value of the signal.
512   * @param[in] sa, the new action with the signal handler.
513   * @param[out] old, the old action with the signal handler.
514   * @retval true if the signal if intercepted, or false.
515   */
intercept_sigaction(int signo,const struct sigaction * restrict sa,struct sigaction * restrict old)516 bool intercept_sigaction(int signo, const struct sigaction *restrict sa,
517                          struct sigaction *restrict old)
518 {
519     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
520     if (signo <= 0 || signo >= _NSIG) {
521         SIGCHAIN_PRINT_ERROR("%{public}s Invalid signal %{public}d", __func__, signo);
522         return false;
523     }
524 
525     if (ismarked(signo)) {
526         struct sigaction saved_action = getaction(signo);
527 
528         if (sa != NULL) {
529             setaction(signo, sa);
530         }
531         if (old != NULL) {
532             *old = saved_action;
533         }
534         return true;
535     }
536 
537     return false;
538 }
539 
540 /**
541   * @brief Intercept the pthread_sigmask.
542   * @param[in] how, the value of the mask operation .
543   * @param[out] set, the value of the sigset.
544   * @retval void.
545   */
intercept_pthread_sigmask(int how,sigset_t * restrict set)546 void intercept_pthread_sigmask(int how, sigset_t *restrict set)
547 {
548     SIGCHAIN_PRINT_DEBUG("%{public}s how: %{public}d", __func__, how);
549     // Forward directly to the system mask When this sigchain is handling a signal.
550     if (get_handling_signal()) {
551         return;
552     }
553 
554     sigset_t tmpset;
555     if (set != NULL) {
556         tmpset = *set;
557         if (how == SIG_BLOCK || how == SIG_SETMASK) {
558             for (int i = 1; i < _NSIG; ++i) {
559                 if (ismarked(i) && sigismember(&tmpset, i)) {
560                     sigdelset(&tmpset, i);
561                 }
562             }
563         }
564         *set = tmpset;
565     }
566 
567     return;
568 }
569