diff --git a/libc-test/src/functionalext/common/sigchain_util.h b/libc-test/src/functionalext/common/sigchain_util.h new file mode 100644 index 0000000000000000000000000000000000000000..494957513f81a3cc4472bd4e3e76fd8d1c641230 --- /dev/null +++ b/libc-test/src/functionalext/common/sigchain_util.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SIG_BLOCK: Mask the signal according to the mask word provided by parameter set. + * And save the original signal mask to oldset + */ +#define SIGCHAIN_TEST_SET_MASK(set, fun, signo, num) do{ \ + int result = sigemptyset(&set); \ + if (result != 0) { \ + EXPECT_FALSE(fun, true); \ + } \ + for (int i = 0; i < num; i++) { \ + result = sigaddset(&set, signo[i]); \ + if (result != 0) { \ + EXPECT_FALSE(fun, true); \ + } \ + } \ + result = sigprocmask(SIG_BLOCK, &set, NULL); \ + if (result != 0) { \ + EXPECT_FALSE(fun, true); \ + } \ +} while (0) + +#define SIGCHIAN_TEST_SIGNAL_NUM_1 1 +#define SIGCHIAN_TEST_SIGNAL_NUM_2 2 +#define SIGCHIAN_TEST_SIGNAL_NUM_3 3 +#define SIGCHIAN_TEST_SIGNAL_NUM_4 4 +#define SIGCHIAN_TEST_SIGNAL_NUM_5 5 +#define SIGCHIAN_TEST_SIGNAL_NUM_6 6 +#define SIGCHIAN_TEST_SIGNAL_NUM_8 8 +#define SIGCHIAN_TEST_SIGNAL_NUM_9 9 +#define SIGCHIAN_TEST_SIGNAL_NUM_11 11 +#define SIGCHIAN_TEST_SIGNAL_NUM_13 13 +#define SIGCHIAN_TEST_SIGNAL_NUM_14 14 + +#define SIGCHAIN_SIGNAL_37 37 +#define SIGCHAIN_SIGNAL_43 43 +#define SIGCHAIN_SIGNAL_64 64 + +extern bool get_sigchain_mask_enable(); \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/BUILD.gn b/libc-test/src/functionalext/sigchain/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..bc9ff895cb7d229cb2957c64ab6e83a75398e283 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("../../../test_template.gni") +import("test_src_functionalext_sigchain.gni") + +foreach(s, functionalext_sigchain_list) { + test_unittest(s) { + target_dir = "functionalext/sigchain" + } +} + +group("functionalext_sigchain_test") { + testonly = true + deps = [] + foreach(s, functionalext_sigchain_list) { + deps += [ ":${s}" ] + } +} diff --git a/libc-test/src/functionalext/sigchain/sigchain_add_special_handler.c b/libc-test/src/functionalext/sigchain/sigchain_add_special_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..3bbbd256fcd9b502ce03ccdca96d1a050a67fee6 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_add_special_handler.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; +/** + * @brief the special handler + */ +static bool sigchain_special_sigabrt_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_001", signo, SIGABRT); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigabrt_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_001", signo, SIGABRT); + return true; +} + +/** + * @tc.name : sigchain_add_special_handler_001 + * @tc.desc : The signal are not registered with the kernel, call add_special_signal_handler to add + * two special handlers + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_001() +{ + struct signal_chain_action sigabrt = { + .sca_sigaction = sigchain_special_sigabrt_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGABRT, &sigabrt); + + struct signal_chain_action sigabrt1 = { + .sca_sigaction = sigchain_special_sigabrt_handler2, + .sca_mask = {}, + .sca_flags = SIGCHAIN_ALLOW_NORETURN, + }; + add_special_signal_handler(SIGABRT, &sigabrt1); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGABRT}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_001", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + raise(SIGABRT); + EXPECT_EQ("sigchain_add_special_handler_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_2); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sighup_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_002", signo, SIGHUP); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sighup_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_002", signo, SIGHUP); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_sighup_handler(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_002", signo, SIGHUP); +} + +/** + * @tc.name : sigchain_add_special_handler_002 + * @tc.desc : The signal are registered with the kernel(Using signal), call + * add_special_signal_handler to add two special handlers + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_002() +{ + signal(SIGHUP, signal_sighup_handler); + + struct signal_chain_action sighup = { + .sca_sigaction = sigchain_special_sighup_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGHUP, &sighup); + + struct signal_chain_action sighup1 = { + .sca_sigaction = sigchain_special_sighup_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGHUP, &sighup1); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGHUP}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + raise(SIGHUP); + EXPECT_EQ("sigchain_add_special_handler_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_5); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigsegv_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_003", signo, SIGSEGV); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigsegv_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_003", signo, SIGSEGV); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_sigsegv_sigaction(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_003", signo, SIGSEGV); +} + +/** + * @tc.name : sigchain_add_special_handler_003 + * @tc.desc : the signal that are registered with the kernel(Using sigaction), call + * add_special_signal_handler to add two special handlers + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_003() +{ + struct sigaction sigac = { + .sa_handler = signal_sigsegv_sigaction, + }; + sigaction(SIGSEGV, &sigac, NULL); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_sigsegv_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + struct signal_chain_action sigsegv2 = { + .sca_sigaction = sigchain_special_sigsegv_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv2); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_003", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + raise(SIGSEGV); + EXPECT_EQ("sigchain_add_special_handler_003", g_count, SIGCHIAN_TEST_SIGNAL_NUM_8); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigterm_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_004", signo, SIGTERM); + return true; +} + +/** + * @tc.name : sigchain_add_special_handler_004 + * @tc.desc : the signal is not registered with the kernel, call add_special_signal_handler to add + * a special handler. + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_004() +{ + struct signal_chain_action sigterm = { + .sca_sigaction = sigchain_special_sigterm_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGTERM, &sigterm); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGTERM}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_004", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + raise(SIGTERM); + EXPECT_EQ("sigchain_add_special_handler_004", g_count, SIGCHIAN_TEST_SIGNAL_NUM_9); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_64_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + EXPECT_EQ("sigchain_add_special_handler_005", signo, SIGCHAIN_SIGNAL_64); + g_count++; + return false; +} + +/** + * @brief the signal handler + */ +static void signal_64_handler(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_005", signo, SIGCHAIN_SIGNAL_64); +} + +/** + * @tc.name : sigchain_add_special_handler_005 + * @tc.desc : the signal is registered with the kernel(Using signal), call add_special_signal_handler to add + * a special handler. + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_005() +{ + signal(SIGCHAIN_SIGNAL_64, signal_64_handler); + + struct signal_chain_action sighup = { + .sca_sigaction = sigchain_special_64_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGCHAIN_SIGNAL_64, &sighup); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGCHAIN_SIGNAL_64}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_005", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + raise(SIGCHAIN_SIGNAL_64); + EXPECT_EQ("sigchain_add_special_handler_005", g_count, SIGCHIAN_TEST_SIGNAL_NUM_11); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_37_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_006", signo, SIGCHAIN_SIGNAL_37); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_37_sigaction(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_006", signo, SIGCHAIN_SIGNAL_37); +} + +/** + * @tc.name : sigchain_add_special_handler_006 + * @tc.desc : the signal is registered with the kernel(Using sigaction), call add_special_signal_handler + * to add a special handler. + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_006() +{ + struct sigaction sigac = { + .sa_handler = signal_37_sigaction, + }; + sigaction(SIGCHAIN_SIGNAL_37, &sigac, NULL); + + struct signal_chain_action sig37 = { + .sca_sigaction = sigchain_special_37_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGCHAIN_SIGNAL_37, &sig37); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGCHAIN_SIGNAL_37}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_006", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + raise(SIGCHAIN_SIGNAL_37); + EXPECT_EQ("sigchain_add_special_handler_006", g_count, SIGCHIAN_TEST_SIGNAL_NUM_13); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_43_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_add_special_handler_007", signo, SIGCHAIN_SIGNAL_43); + return true; +} + +/** + * @brief the signal handler + */ +static void signal_43_sigaction(int signo) +{ + g_count++; + EXPECT_FALSE("sigchain_intercept_sigprocmask_003", true); +} + +/** + * @tc.name : sigchain_add_special_handler_007 + * @tc.desc : Multiple signal are registered with the kernel(Using sigaction), sigchain_special_43_handler return + * true. + * @tc.level : Level 0 + */ +static void sigchain_add_special_handler_007() +{ + struct sigaction sigac = { + .sa_handler = signal_43_sigaction, + }; + sigaction(SIGCHAIN_SIGNAL_43, &sigac, NULL); + + struct signal_chain_action sig43 = { + .sca_sigaction = sigchain_special_43_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGCHAIN_SIGNAL_43, &sig43); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGCHAIN_SIGNAL_43}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_add_special_handler_007", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + raise(SIGCHAIN_SIGNAL_43); + EXPECT_EQ("sigchain_add_special_handler_007", g_count, SIGCHIAN_TEST_SIGNAL_NUM_14); +} + +int main(void) +{ + sigchain_add_special_handler_001(); + sigchain_add_special_handler_002(); + sigchain_add_special_handler_003(); + sigchain_add_special_handler_004(); + sigchain_add_special_handler_005(); + sigchain_add_special_handler_006(); + sigchain_add_special_handler_007(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/sigchain_handler_call_order.c b/libc-test/src/functionalext/sigchain/sigchain_handler_call_order.c new file mode 100644 index 0000000000000000000000000000000000000000..2c402812b4a9e9d6a8f466caaad835c2b6e14c8e --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_handler_call_order.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; + +/** + * @brief the special handler + */ +static bool sigchain_special_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + EXPECT_EQ("sigchain_handler_call_order_001", signo, SIGHUP); + sigset_t set = {0}; + int signal[SIGCHIAN_TEST_SIGNAL_NUM_2] = {SIGHUP, SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigprocmask_001", signal, SIGCHIAN_TEST_SIGNAL_NUM_2); + raise(SIGSEGV); + g_count++; + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + EXPECT_EQ("sigchain_handler_call_order_001", signo, SIGSEGV); + EXPECT_EQ("sigchain_handler_call_order_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_1); + g_count++; + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler(int signo) +{ + g_count++; +} + +/** + * @tc.name : sigchain_handler_call_order_001 + * @tc.desc : The signals are registered with the special handler, and mask and rasie the signal + * at the special handler. Test the influence of sigchain on sigprocmask. + * @tc.level : Level 0 + */ +static void sigchain_handler_call_order_001() +{ + signal(SIGHUP, signal_handler); + signal(SIGSEGV, signal_handler); + + struct signal_chain_action sighup = { + .sca_sigaction = sigchain_special_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGHUP, &sighup); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + raise(SIGHUP); + EXPECT_EQ("sigchain_handler_call_order_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_4); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler3(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + EXPECT_EQ("sigchain_handler_call_order_002", signo, SIGSYS); + g_count++; + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler3(int signo) +{ + EXPECT_EQ("sigchain_handler_call_order_002", signo, SIGSYS); + EXPECT_EQ("sigchain_handler_call_order_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_5); + g_count++; + return; +} + +/** + * @tc.name : sigchain_handler_call_order_002 + * @tc.desc : Add a special handler for a signal that is registered with + * the kernel (Using signal interface) in sigchain. + * @tc.level : Level 0 + */ +static void sigchain_handler_call_order_002() +{ + signal(SIGSYS, signal_handler3); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler3, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSYS, &sigsegv); + + raise(SIGSYS); + EXPECT_EQ("sigchain_handler_call_order_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_6); +} + +int main(void) +{ + sigchain_handler_call_order_001(); + sigchain_handler_call_order_002(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/sigchain_intercept_sigaction.c b/libc-test/src/functionalext/sigchain/sigchain_intercept_sigaction.c new file mode 100644 index 0000000000000000000000000000000000000000..f27ed9b55674c3e33e46e11ce686c1ab45798f06 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_intercept_sigaction.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; +/** + * @brief the special handler + */ +static void signal_handler1(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigaction_001", signo, SIGHUP); +} + +/** + * @tc.name : sigchain_intercept_sigaction_001 + * @tc.desc : The signals are not registered with the special handler, test the influence of sigchain + * on sigaction. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigaction_001() +{ + struct sigaction siga1 = { + .sa_handler = signal_handler1, + }; + sigaction(SIGHUP, &siga1, NULL); + + raise(SIGHUP); + EXPECT_EQ("sigchain_intercept_sigaction_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_1); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigaction_002", signo, SIGSEGV); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler2(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigaction_002", signo, SIGSEGV); +} + + +/** + * @tc.name : sigchain_intercept_sigaction_002 + * @tc.desc : The signals are registered with the special handler, test the influence of sigchain on sigaction. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigaction_002() +{ + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + struct sigaction siga2 = { + .sa_handler = signal_handler2, + }; + sigaction(SIGSEGV, &siga2, NULL); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigaction_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + raise(SIGSEGV); + EXPECT_EQ("sigchain_intercept_sigaction_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_3); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler3(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigaction_003", signo, SIGURG); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler3(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigaction_003", signo, SIGURG); +} + +/** + * @tc.name : sigchain_intercept_sigaction_003 + * @tc.desc : the signals are registered with the special handler, and remove the special handler. Test + * the influence of sigchain on sigaction. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigaction_003() +{ + struct signal_chain_action sigurg = { + .sca_sigaction = sigchain_special_handler3, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGURG, &sigurg); + + struct sigaction siga2 = { + .sa_handler = signal_handler3, + }; + sigaction(SIGURG, &siga2, NULL); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGURG}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigaction_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + remove_special_signal_handler(SIGURG, sigchain_special_handler3); + raise(SIGURG); + EXPECT_EQ("sigchain_intercept_sigaction_003", g_count, SIGCHIAN_TEST_SIGNAL_NUM_4); +} +int main(void) +{ + sigchain_intercept_sigaction_001(); + sigchain_intercept_sigaction_002(); + sigchain_intercept_sigaction_003(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/sigchain_intercept_signal.c b/libc-test/src/functionalext/sigchain/sigchain_intercept_signal.c new file mode 100644 index 0000000000000000000000000000000000000000..f8399f6558d26e73f172054bea89809cf9cba0f7 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_intercept_signal.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; +/** + * @brief the signal handler + */ +static void signal_handler1(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_signal_001", signo, SIGHUP); +} + +/** + * @tc.name : sigchain_add_special_handler_025 + * @tc.desc : The signals are not registered with the special handler, test the influence of sigchain on signal + * @tc.level : Level 0 + */ +static void sigchain_intercept_signal_001() +{ + signal(SIGHUP, signal_handler1); + raise(SIGHUP); + EXPECT_EQ("sigchain_intercept_signal_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_1); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_signal_002", signo, SIGSEGV); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler2(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_signal_002", signo, SIGSEGV); +} + +/** + * @tc.name : sigchain_intercept_signal_002 + * @tc.desc : The signals are registered with the special handler, test the influence of sigchain on signal + * @tc.level : Level 0 + */ +static void sigchain_intercept_signal_002() +{ + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + signal(SIGSEGV, signal_handler2); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_signal_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + raise(SIGSEGV); + EXPECT_EQ("sigchain_intercept_signal_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_3); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler3(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_signal_003", signo, SIGURG); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler3(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_signal_003", signo, SIGURG); +} + + +/** + * @tc.name : sigchain_intercept_signal_003 + * @tc.desc : The signals are registered with the special handler, and remove the special handler. + * Test the influence of sigchain on signal + * @tc.level : Level 0 + */ +static void sigchain_intercept_signal_003() +{ + struct signal_chain_action sigurg = { + .sca_sigaction = sigchain_special_handler3, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGURG, &sigurg); + + signal(SIGURG, signal_handler3); + + remove_special_signal_handler(SIGURG, sigchain_special_handler3); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGURG}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigaction_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + raise(SIGURG); + EXPECT_EQ("sigchain_intercept_signal_003", g_count, SIGCHIAN_TEST_SIGNAL_NUM_4); +} +int main(void) +{ + sigchain_intercept_signal_001(); + sigchain_intercept_signal_002(); + sigchain_intercept_signal_003(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/sigchain_intercept_sigprocmask.c b/libc-test/src/functionalext/sigchain/sigchain_intercept_sigprocmask.c new file mode 100644 index 0000000000000000000000000000000000000000..9d996b1ef7e8063227a4ae08e470f21d0c4da7b2 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_intercept_sigprocmask.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; + +/** + * @brief the special handler + */ +static bool sigchain_special_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigprocmask_001", signo, SIGSEGV); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler2(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigprocmask_001", signo, SIGSEGV); +} + +/** + * @tc.name : sigchain_intercept_sigprocmask_001 + * @tc.desc : The signals are registered with the special handler, test the influence of sigchain + * on sigprocmask. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigprocmask_001() +{ + struct sigaction siga2 = { + .sa_handler = signal_handler2, + }; + sigaction(SIGSEGV, &siga2, NULL); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigprocmask_001", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + raise(SIGSEGV); + if (get_sigchain_mask_enable()) { + EXPECT_EQ("sigchain_intercept_sigprocmask_001", g_count, SIGCHIAN_TEST_SIGNAL_NUM_2); + } else { + EXPECT_EQ("sigchain_intercept_sigprocmask_001", g_count, 0); + } +} + +/** + * @brief the special handler + */ +static bool sigchain_special_handler3(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_intercept_sigprocmask_002", true); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_handler3(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_intercept_sigprocmask_002", signo, SIGSYS); +} + +/** + * @tc.name : sigchain_intercept_sigprocmask_002 + * @tc.desc : The signals are registered with the special handler, and remove the special handler. + * Test the influence of sigchain on sigprocmask. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigprocmask_002() +{ + struct sigaction siga2 = { + .sa_handler = signal_handler3, + }; + sigaction(SIGSYS, &siga2, NULL); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_handler3, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSYS, &sigsegv); + + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSYS}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigprocmask_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + + remove_special_signal_handler(SIGSYS, sigchain_special_handler3); + + raise(SIGSYS); + if (get_sigchain_mask_enable()) { + EXPECT_EQ("sigchain_intercept_sigprocmask_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_3); + } else { + EXPECT_EQ("sigchain_intercept_sigprocmask_002", g_count, 0); + } +} + + +/** + * @brief the signal handler + */ +static void signal_handler1(int signo) +{ + g_count++; + EXPECT_FALSE("sigchain_intercept_sigprocmask_001", true); +} + +/** + * @tc.name : sigchain_intercept_sigprocmask_003 + * @tc.desc : The signals are not registered with the special handler, test the influence of sigchain + * on sigprocmask. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigprocmask_003() +{ + struct sigaction siga1 = { + .sa_handler = signal_handler1, + }; + sigaction(SIGHUP, &siga1, NULL); + + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGHUP}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_intercept_sigprocmask_003", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + raise(SIGHUP); + if (get_sigchain_mask_enable()) { + EXPECT_EQ("sigchain_intercept_sigprocmask_003", g_count, SIGCHIAN_TEST_SIGNAL_NUM_3); + } else { + EXPECT_EQ("sigchain_intercept_sigprocmask_003", g_count, 0); + } +} + +/** + * @tc.name : sigchain_intercept_sigprocmask_004 + * @tc.desc : The new set is null, call sigprocmask. + * @tc.level : Level 0 + */ +static void sigchain_intercept_sigprocmask_004() +{ + int result = sigprocmask(SIG_BLOCK, NULL, NULL); + if (result != 0) { + EXPECT_FALSE("sigchain_intercept_sigprocmask_004", true); + } +} +int main(void) +{ + sigchain_intercept_sigprocmask_001(); + sigchain_intercept_sigprocmask_002(); + sigchain_intercept_sigprocmask_003(); + sigchain_intercept_sigprocmask_004(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/sigchain_rm_special_handler.c b/libc-test/src/functionalext/sigchain/sigchain_rm_special_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..0c5962f459424255e7573cba96a1643959919cff --- /dev/null +++ b/libc-test/src/functionalext/sigchain/sigchain_rm_special_handler.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "test.h" +#include "functionalext.h" +#include "sigchain_util.h" + +static int g_count = 0; +/** + * @brief the special handler + */ +static bool sigchain_special_sigabrt_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_001", true); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigabrt_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_001", true); + return true; +} + +/** + * @tc.name : sigchain_rm_special_handler_001 + * @tc.desc : The signal are not registered with the kernel, call remove_special_signal_handler to remove + * two special handlers + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_001() +{ + struct signal_chain_action sigabrt = { + .sca_sigaction = sigchain_special_sigabrt_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGABRT, &sigabrt); + + struct signal_chain_action sigabrt1 = { + .sca_sigaction = sigchain_special_sigabrt_handler2, + .sca_mask = {}, + .sca_flags = SIGCHAIN_ALLOW_NORETURN, + }; + add_special_signal_handler(SIGABRT, &sigabrt1); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGABRT}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_001", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + remove_special_signal_handler(SIGABRT, sigchain_special_sigabrt_handler1); + remove_special_signal_handler(SIGABRT, sigchain_special_sigabrt_handler2); + + raise(SIGABRT); + EXPECT_EQ("sigchain_rm_special_handler_001", g_count, 0); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sighup_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_002", true); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sighup_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_002", true); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_sighup_handler(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_rm_special_handler_002", signo, SIGHUP); +} + +/** + * @tc.name : sigchain_rm_special_handler_002 + * @tc.desc : The signal are registered with the kernel(Using signal), call + * remove_special_signal_handler to remove two special handlers + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_002() +{ + signal(SIGHUP, signal_sighup_handler); + + struct signal_chain_action sighup = { + .sca_sigaction = sigchain_special_sighup_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGHUP, &sighup); + + struct signal_chain_action sighup1 = { + .sca_sigaction = sigchain_special_sighup_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGHUP, &sighup1); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGHUP}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_002", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + remove_special_signal_handler(SIGHUP, sigchain_special_sighup_handler1); + remove_special_signal_handler(SIGHUP, sigchain_special_sighup_handler2); + + raise(SIGHUP); + EXPECT_EQ("sigchain_rm_special_handler_002", g_count, SIGCHIAN_TEST_SIGNAL_NUM_1); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigsegv_handler1(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_003", true); + return false; +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigsegv_handler2(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_003", true); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_sigsegv_sigaction(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_rm_special_handler_003", signo, SIGSEGV); +} + +/** + * @tc.name : sigchain_rm_special_handler_003 + * @tc.desc : the signal that are registered with the kernel(Using sigaction), call + * remove_special_signal_handler to remove two special handlers + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_003() +{ + struct sigaction sigac = { + .sa_handler = signal_sigsegv_sigaction, + }; + sigaction(SIGSEGV, &sigac, NULL); + + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_sigsegv_handler1, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv); + + struct signal_chain_action sigsegv2 = { + .sca_sigaction = sigchain_special_sigsegv_handler2, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGSEGV, &sigsegv2); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGSEGV}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_003", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + + remove_special_signal_handler(SIGSEGV, sigchain_special_sigsegv_handler1); + remove_special_signal_handler(SIGSEGV, sigchain_special_sigsegv_handler2); + raise(SIGSEGV); + EXPECT_EQ("sigchain_rm_special_handler_003", g_count, SIGCHIAN_TEST_SIGNAL_NUM_2); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_sigterm_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_004", true); + return true; +} + +/** + * @tc.name : sigchain_rm_special_handler_004 + * @tc.desc : the signal is not registered with the kernel, call remove_special_signal_handler to remove + * a special handler. + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_004() +{ + struct signal_chain_action sigsegv = { + .sca_sigaction = sigchain_special_sigterm_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGTERM, &sigsegv); + + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGTERM}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_004", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + remove_special_signal_handler(SIGTERM, sigchain_special_sigterm_handler); + + raise(SIGTERM); + EXPECT_EQ("sigchain_rm_special_handler_004", g_count, SIGCHIAN_TEST_SIGNAL_NUM_2); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_64_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + EXPECT_FALSE("sigchain_rm_special_handler_005", true); + g_count++; + return false; +} + +/** + * @brief the signal handler + */ +static void signal_64_handler(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_rm_special_handler_005", signo, SIGCHAIN_SIGNAL_64); +} + +/** + * @tc.name : sigchain_rm_special_handler_005 + * @tc.desc : the signal is registered with the kernel(Using signal), call remove_special_signal_handler to remove + * a special handler. + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_005() +{ + signal(SIGCHAIN_SIGNAL_64, signal_64_handler); + + + struct signal_chain_action sighup = { + .sca_sigaction = sigchain_special_64_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGCHAIN_SIGNAL_64, &sighup); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGCHAIN_SIGNAL_64}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_005", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + remove_special_signal_handler(SIGCHAIN_SIGNAL_64, sigchain_special_64_handler); + + raise(SIGCHAIN_SIGNAL_64); + EXPECT_EQ("sigchain_rm_special_handler_005", g_count, SIGCHIAN_TEST_SIGNAL_NUM_3); +} + +/** + * @brief the special handler + */ +static bool sigchain_special_37_handler(int signo, siginfo_t *siginfo, void *ucontext_raw) +{ + g_count++; + EXPECT_FALSE("sigchain_rm_special_handler_006", true); + return false; +} + +/** + * @brief the signal handler + */ +static void signal_37_sigaction(int signo) +{ + g_count++; + EXPECT_EQ("sigchain_rm_special_handler_006", signo, SIGCHAIN_SIGNAL_37); +} + +/** + * @tc.name : sigchain_rm_special_handler_006 + * @tc.desc : the signal is registered with the kernel(Using sigaction), call remove_special_signal_handler + * to remove a special handler. + * @tc.level : Level 0 + */ +static void sigchain_rm_special_handler_006() +{ + struct sigaction sigac = { + .sa_handler = signal_37_sigaction, + }; + sigaction(SIGCHAIN_SIGNAL_37, &sigac, NULL); + + struct signal_chain_action sig37 = { + .sca_sigaction = sigchain_special_37_handler, + .sca_mask = {}, + .sca_flags = 0, + }; + add_special_signal_handler(SIGCHAIN_SIGNAL_37, &sig37); + + if (get_sigchain_mask_enable()) { + sigset_t set = {0}; + int signo[SIGCHIAN_TEST_SIGNAL_NUM_1] = {SIGCHAIN_SIGNAL_37}; + SIGCHAIN_TEST_SET_MASK(set, "sigchain_rm_special_handler_006", signo, SIGCHIAN_TEST_SIGNAL_NUM_1); + } + remove_special_signal_handler(SIGCHAIN_SIGNAL_37, sigchain_special_37_handler); + + raise(SIGCHAIN_SIGNAL_37); + EXPECT_EQ("sigchain_rm_special_handler_006", g_count, SIGCHIAN_TEST_SIGNAL_NUM_4); +} + +int main(void) +{ + sigchain_rm_special_handler_001(); + sigchain_rm_special_handler_002(); + sigchain_rm_special_handler_003(); + sigchain_rm_special_handler_004(); + sigchain_rm_special_handler_005(); + sigchain_rm_special_handler_006(); + return t_status; +} \ No newline at end of file diff --git a/libc-test/src/functionalext/sigchain/test_src_functionalext_sigchain.gni b/libc-test/src/functionalext/sigchain/test_src_functionalext_sigchain.gni new file mode 100644 index 0000000000000000000000000000000000000000..4a4086b9043d52b3e794dab4815ec13ca2ec7310 --- /dev/null +++ b/libc-test/src/functionalext/sigchain/test_src_functionalext_sigchain.gni @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +functionalext_sigchain_list = [ + "sigchain_add_special_handler", + "sigchain_rm_special_handler", + "sigchain_intercept_sigaction", + "sigchain_intercept_signal", + "sigchain_intercept_sigprocmask", + "sigchain_handler_call_order", +] diff --git a/libc-test/src/functionalext/test_src_functionalext.gni b/libc-test/src/functionalext/test_src_functionalext.gni index f5b04dfee1910d1a232cddd8dafb7149fc665f51..f00f3e09191684b8678ff75a0bae23d5c01c611f 100644 --- a/libc-test/src/functionalext/test_src_functionalext.gni +++ b/libc-test/src/functionalext/test_src_functionalext.gni @@ -29,4 +29,5 @@ functionalext_list = [ "sched:functionalext_sched_test", "unittest:functionalext_unittest_test", "legacy:functionalext_legacy_test", + "sigchain:functionalext_sigchain_test", ] diff --git a/libc-test/test_template.gni b/libc-test/test_template.gni index c09f53f300ebdf9d832e394759cf9c10aaffdd35..23b374de96c66edb9a2be5ce4ce75d07ef766997 100644 --- a/libc-test/test_template.gni +++ b/libc-test/test_template.gni @@ -233,6 +233,10 @@ template("test_unittest") { } } } + + if (target_dir == "functionalext/sigchain") { + include_dirs += [ "//${musl_base_dir}/include" ] + } } } diff --git a/libc.map.txt b/libc.map.txt index ddbe5ddd7eb33aff211fa72030398bb0440fe676..9309b1012338697464c3d3d76f8c6ddaff4532d9 100644 --- a/libc.map.txt +++ b/libc.map.txt @@ -310,6 +310,7 @@ acoshl; acosl; addmntent; + add_special_signal_handler; adjtime; adjtimex; aio_cancel; @@ -1486,6 +1487,7 @@ remainderl; remap_file_pages; remove; + remove_special_signal_handler; removexattr; remque; remquo; diff --git a/musl_src.gni b/musl_src.gni index 189d27e65abc3b9b049146d211cddf23ddc81d53..03a3e66d4c9d751007a6b2003d65a33a538ebe7b 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -1040,6 +1040,7 @@ musl_src_file = [ "src/signal/sigtimedwait.c", "src/signal/sigwait.c", "src/signal/sigwaitinfo.c", + "src/sigchain/sigchain.c", "src/stat/__xstat.c", "src/stat/chmod.c", "src/stat/fchmod.c", @@ -1974,6 +1975,7 @@ musl_inc_root_files = [ "include/setjmp.h", "include/shadow.h", "include/signal.h", + "include/sigchain.h", "include/spawn.h", "include/stdalign.h", "include/stdarg.h", @@ -2043,6 +2045,7 @@ musl_src_porting_file = [ "include/sys/socket.h", "include/sys/sysinfo.h", "include/signal.h", + "include/sigchain.h", "include/sched.h", "src/internal/dynlink.h", "include/sys/tgkill.h", @@ -2116,6 +2119,8 @@ musl_src_porting_file = [ "src/thread/pthread_create.c", "src/sched/sched_cpualloc.c", "src/signal/signal.c", + "src/signal/sigaction.c", + "src/signal/sigprocmask.c", "include/langinfo.h", "include/locale.h", "src/hilog/hilog_adapter.c", @@ -2147,6 +2152,7 @@ musl_src_porting_file = [ "src/process/x86_64/__vfork.s", "src/linux/cache.c", "src/sched/sched_getcpu.c", + "src/sigchain/sigchain.c", ] musl_inc_hook_files = [ diff --git a/porting/linux/user/include/sigchain.h b/porting/linux/user/include/sigchain.h new file mode 100644 index 0000000000000000000000000000000000000000..cde6ab6a0c620d98fee828476ece6719bdcfe7b5 --- /dev/null +++ b/porting/linux/user/include/sigchain.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SIGCHAIN_H +#define _SIGCHAIN_H + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int SIGCHAIN_ALLOW_NORETURN = 0x1UL; + +/* The action of the sigchain. */ +struct signal_chain_action { + bool (*sca_sigaction)(int, siginfo_t*, void*); + sigset_t sca_mask; + int sca_flags; +}; + +/* Mark the signal to the sigchain, add the special handler to the sigchain. */ +void add_special_signal_handler(int signo, struct signal_chain_action* sa); +/* Remove the special the handler form the sigchain. */ +void remove_special_signal_handler(int signo, bool (*fn)(int, siginfo_t*, void*)); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/porting/linux/user/src/sigchain/sigchain.c b/porting/linux/user/src/sigchain/sigchain.c new file mode 100644 index 0000000000000000000000000000000000000000..f26d92c2704ce8e4d9699d8300e8dfff93d1fa8c --- /dev/null +++ b/porting/linux/user/src/sigchain/sigchain.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +extern int __libc_sigaction(int sig, const struct sigaction *restrict sa, + struct sigaction *restrict old); + +#define SIG_CHAIN_KEY_VALUE_1 1 +#define SIGNAL_CHAIN_SPECIAL_ACTION_MAX 2 + +#define SIGCHAIN_LOG_DOMAIN 0xD003F00 +#define SIGCHAIN_LOG_TAG "SIGCHAIN" + +#if (defined(OHOS_ENABLE_PARAMETER) || defined(ENABLE_MUSL_LOG)) +#define SIGCHAIN_PRINT_ERROR(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_ERROR, \ + SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__)) +#define SIGCHAIN_PRINT_INFO(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_INFO, \ + SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__)) +#define SIGCHAIN_PRINT_DEBUG(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_DEBUG, \ + SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__)) +#define SIGCHAIN_LOG_FATAL(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_FATAL, \ + SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__)) +#else +#define SIGCHAIN_PRINT_ERROR(...) +#define SIGCHAIN_PRINT_INFO(...) +#define SIGCHAIN_PRINT_DEBUG(...) +#define SIGCHAIN_LOG_FATAL(...) +#endif + +#define SIGCHAIN_PRINT_FATAL(...) do { \ + SIGCHAIN_LOG_FATAL(__VA_ARGS__); \ + abort(); \ +} while(0) + +struct sc_signal_chain { + bool marked; + struct sigaction sig_action; + struct signal_chain_action sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX]; +}; + +/* Signal chain set, from 0 to 63. */ +static struct sc_signal_chain sig_chains[_NSIG - 1]; +/* static thread Keyword */ +static pthread_key_t g_sigchain_key; +/* This is once flag! */ +static once_flag g_flag = ONCE_FLAG_INIT; + +/** + * @brief Create the thread key + * @retval void + */ +static void create_pthread_key(void) +{ + SIGCHAIN_PRINT_INFO("%{public}s create the thread key!", __func__); + int rc = pthread_key_create(&g_sigchain_key, NULL); + if (rc != 0) { + SIGCHAIN_PRINT_ERROR("%{public}s failed to create sigchain pthread key, rc:%{public}d", + __func__, rc); + } +} + + +/** + * @brief Get the key of the signal thread. + * @retval int32_t, the value of the sigchain key. + */ +static pthread_key_t get_handling_signal_key() +{ + call_once(&g_flag, create_pthread_key); + return g_sigchain_key; +} + +/** + * @brief Get the value of the sigchain key + * @retval bool, true if set the value of the key,or false. + */ +static bool get_handling_signal() +{ + void *result = pthread_getspecific(get_handling_signal_key()); + return result == NULL ? false : true; +} + +/** + * @brief Set the value of the sigchain key + * @param[in] value, the value of the sigchain key + * @retval void. + */ +static void set_handling_signal(bool value) +{ + pthread_setspecific(get_handling_signal_key(), + (void *)((uintptr_t)(value))); +} + +/** + * @brief Judge whether the signal is marked + * @param[in] signo, the value of the signal. + * @retval true if the signal is marked, or false. + */ +bool ismarked(int signo) +{ + return sig_chains[signo - 1].marked; +} + +/** + * @brief This is a callback function, which is registered to the kernel + * @param[in] signo, the value of the signal. + * @param[in] siginfo, the information of the signal. + * @param[in] ucontext_raw, the context of the signal. + * @retval void + */ +static void signal_chain_handler(int signo, siginfo_t* siginfo, void* ucontext_raw) +{ + SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo); + /* First call special handler. */ + /* If a process crashes, the sigchain'll call the corresponding handler */ + if (!get_handling_signal()) { + for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) { + if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == NULL) { + break; + } + /* The special handler might not return. */ + bool noreturn = (sig_chains[signo - 1].sca_special_actions[i].sca_flags & + SIGCHAIN_ALLOW_NORETURN); + sigset_t previous_mask; + pthread_sigmask(SIG_SETMASK, &sig_chains[signo - 1].sca_special_actions[i].sca_mask, + &previous_mask); + + bool previous_value = get_handling_signal(); + if (!noreturn) { + set_handling_signal(true); + } + + if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction(signo, + siginfo, ucontext_raw)) { + set_handling_signal(previous_value); + return; + } + + pthread_sigmask(SIG_SETMASK, &previous_mask, NULL); + set_handling_signal(previous_value); + } + } + /* Then Call the user's signal handler */ + int sa_flags = sig_chains[signo - 1].sig_action.sa_flags; + ucontext_t* ucontext = (ucontext_t*)(ucontext_raw); + + sigset_t mask; + sigorset(&mask, &ucontext->uc_sigmask, &sig_chains[signo - 1].sig_action.sa_mask); + + if (!(sa_flags & SA_NODEFER)) { + sigaddset(&mask, signo); + } + + pthread_sigmask(SIG_SETMASK, &mask, NULL); + + if ((sa_flags & SA_SIGINFO)) { + sig_chains[signo - 1].sig_action.sa_sigaction(signo, siginfo, ucontext_raw); + } else { + if (sig_chains[signo - 1].sig_action.sa_handler == SIG_IGN) { + return; + } else if (sig_chains[signo - 1].sig_action.sa_handler == SIG_DFL) { + SIGCHAIN_PRINT_INFO("%{public}s exiting due to SIG_DFL handler for signal: %{public}d", + __func__, signo); + } else { + sig_chains[signo - 1].sig_action.sa_handler(signo); + } + } + + return; +} + +/** + * @brief Register the signal chain with the kernel if needed + * @param[in] signo, the value of the signal. + * @retval void + */ +static void sigchain_register(int signo) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + struct sigaction signal_action = {}; + sigfillset(&signal_action.sa_mask); + + signal_action.sa_sigaction = signal_chain_handler; + signal_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; + __libc_sigaction(signo, &signal_action, &sig_chains[signo - 1].sig_action); +} + +/** + * @brief Mark the signal to the sigchain. + * @param[in] signo, the value of the signal. + * @retval void + */ +static void mark_signal_to_sigchain(int signo) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + if (!sig_chains[signo - 1].marked) { + sigchain_register(signo); + sig_chains[signo - 1].marked = true; + } +} + +/** + * @brief Set the action of the signal. + * @param[in] signo, the value of the signal. + * @param[in] new_sa, the new action of the signal. + * @retval void + */ +static void setaction(int signo, const struct sigaction *restrict new_sa) +{ + SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo); + sig_chains[signo - 1].sig_action = *new_sa; +} + +/** + * @brief Get the action of the signal. + * @param[in] signo, the value of the signal. + * @retval The current action of the signal + */ +static struct sigaction getaction(int signo) +{ + SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo); + return sig_chains[signo - 1].sig_action; +} + +/** + * @brief Add the special handler to the sigchain. + * @param[in] signo, the value of the signal. + * @param[in] sa, the action with special handler. + * @retval void + */ +void add_special_handler(int signo, struct signal_chain_action* sa) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) { + if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == NULL) { + sig_chains[signo - 1].sca_special_actions[i] = *sa; + SIGCHAIN_PRINT_INFO("%{public}s signo %{public}d is registered with special handler!", __func__, signo); + return; + } + } + + SIGCHAIN_PRINT_FATAL("Add too many the special handlers!"); +} + +/** + * @brief Remove the special handler from the sigchain. + * @param[in] signo, the value of the signal. + * @param[in] fn, the special handler of the signal. + * @retval void + */ +void rm_special_handler(int signo, bool (*fn)(int, siginfo_t*, void*)) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + int len = SIGNAL_CHAIN_SPECIAL_ACTION_MAX; + for (int i = 0; i < len; i++) { + if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == fn) { + for (int j = i; j < len - 1; ++j) { + sig_chains[signo - 1].sca_special_actions[j] = + sig_chains[signo - 1].sca_special_actions[j + 1]; + } + sig_chains[signo - 1].sca_special_actions[len - 1].sca_sigaction = NULL; + return; + } + } + + SIGCHAIN_PRINT_FATAL("%{public}s failed to remove the special handler!. signo: %{public}d", + __func__, signo); +} + +/** + * @brief This is an external interface, + * Mark the signal to sigchain ,add the special handler to the sigchain. + * @param[in] signo, the value of the signal. + * @param[in] sa, the action with special handler. + * @retval void + */ +void add_special_signal_handler(int signo, struct signal_chain_action* sa) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + if (signo <= 0 || signo >= _NSIG) { + SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo); + return; + } + + // Add the special hander to the sigchain + add_special_handler(signo, sa); + mark_signal_to_sigchain(signo); +} + +/** + * @brief This is an external interface, remove the special handler from the sigchain. + * @param[in] signo, the value of the signal. + * @param[in] fn, the special handler of the signal. + * @retval void + */ +void remove_special_signal_handler(int signo, bool (*fn)(int, siginfo_t*, void*)) +{ + SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo); + if (signo <= 0 || signo >= _NSIG) { + SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo); + return; + } + // remove the special handler from the sigchain. + rm_special_handler(signo, fn); +} + +/** + * @brief Intercept the signal and sigaction. + * @param[in] signo, the value of the signal. + * @param[in] sa, the new action with the signal handler. + * @param[out] old, the old action with the signal handler. + * @retval true if the signal if intercepted, or false. + */ +bool intercept_sigaction(int signo, const struct sigaction *restrict sa, + struct sigaction *restrict old) +{ + SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo); + if (signo <= 0 || signo >= _NSIG) { + SIGCHAIN_PRINT_ERROR("%{public}s Invalid signal %{public}d", __func__, signo); + return false; + } + + if (ismarked(signo)) { + struct sigaction saved_action = getaction(signo); + + if (sa != NULL) { + setaction(signo, sa); + } + if (old != NULL) { + *old = saved_action; + } + return true; + } + + return false; +} + +/** + * @brief Intercept the sigprocmask. + * @param[in] how, the value of the mask operation . + * @param[out] set, the value of the sigset. + * @retval void. + */ +void intercept_sigprocmask(int how, sigset_t *restrict set) +{ + SIGCHAIN_PRINT_DEBUG("%{public}s how: %{public}d", __func__, how); + // Forward directly to the pthread_sigmask When this sigchain is handling a signal. + if (get_handling_signal()) { + return; + } + + sigset_t tmpset; + if (set != NULL) { + tmpset = *set; + if (how == SIG_BLOCK || how == SIG_SETMASK) { + for (int i = 1; i < _NSIG; ++i) { + if (ismarked(i) && sigismember(&tmpset, i)) { + sigdelset(&tmpset, i); + } + } + } + *set = tmpset; + } + + return; +} diff --git a/porting/linux/user/src/signal/sigaction.c b/porting/linux/user/src/signal/sigaction.c new file mode 100644 index 0000000000000000000000000000000000000000..0651867348e720611895db9f3804afdb3416d51b --- /dev/null +++ b/porting/linux/user/src/signal/sigaction.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include "syscall.h" +#include "pthread_impl.h" +#include "libc.h" +#include "lock.h" +#include "ksigaction.h" + +extern bool intercept_sigaction(int signo, const struct sigaction *restrict sa, struct sigaction *restrict old); + +static volatile int dummy_lock[1] = { 0 }; + +extern hidden volatile int __abort_lock[1]; + +weak_alias(dummy_lock, __abort_lock); + +static int unmask_done; +static unsigned long handler_set[_NSIG/(8*sizeof(long))]; + +void __get_handler_set(sigset_t *set) +{ + memcpy(set, handler_set, sizeof handler_set); +} + +volatile int __eintr_valid_flag; + +int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) +{ + struct k_sigaction ksa, ksa_old; + unsigned long set[_NSIG/(8*sizeof(long))]; + if (sa) { + if ((uintptr_t)sa->sa_handler > 1UL) { + a_or_l(handler_set+(sig-1)/(8*sizeof(long)), + 1UL<<(sig-1)%(8*sizeof(long))); + + /* If pthread_create has not yet been called, + * implementation-internal signals might not + * yet have been unblocked. They must be + * unblocked before any signal handler is + * installed, so that an application cannot + * receive an illegal sigset_t (with them + * blocked) as part of the ucontext_t passed + * to the signal handler. */ + if (!libc.threaded && !unmask_done) { + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + SIGPT_SET, 0, _NSIG/8); + unmask_done = 1; + } + + if (!(sa->sa_flags & SA_RESTART)) { + a_store(&__eintr_valid_flag, 1); + } + } + /* Changing the disposition of SIGABRT to anything but + * SIG_DFL requires a lock, so that it cannot be changed + * while abort is terminating the process after simply + * calling raise(SIGABRT) failed to do so. */ + if (sa->sa_handler != SIG_DFL && sig == SIGABRT) { + __block_all_sigs(&set); + LOCK(__abort_lock); + } + ksa.handler = sa->sa_handler; + ksa.flags = sa->sa_flags | SA_RESTORER; + ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore; + memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8); + } + int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8); + if (sig == SIGABRT && sa && sa->sa_handler != SIG_DFL) { + UNLOCK(__abort_lock); + __restore_sigs(&set); + } + if (old && !r) { + old->sa_handler = ksa_old.handler; + old->sa_flags = ksa_old.flags; + memcpy(&old->sa_mask, &ksa_old.mask, _NSIG/8); + } + return __syscall_ret(r); +} + +int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) +{ + if (sig-32U < 3 || sig-1U >= _NSIG-1) { + errno = EINVAL; + return -1; + } + if (intercept_sigaction(sig, sa, old)) { + return 0; + } + + return __libc_sigaction(sig, sa, old); +} + +weak_alias(__sigaction, sigaction); diff --git a/porting/linux/user/src/signal/sigprocmask.c b/porting/linux/user/src/signal/sigprocmask.c new file mode 100644 index 0000000000000000000000000000000000000000..ca099dd6e18ebd80d9faf615ff266689530f5cc6 --- /dev/null +++ b/porting/linux/user/src/signal/sigprocmask.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#ifdef OHOS_ENABLE_PARAMETER +#include "sys_param.h" +#endif + +extern void intercept_sigprocmask(int how, sigset_t *restrict set); +static const char *param_name = "musl.sigchain.procmask"; + +bool get_sigchain_mask_enable() +{ +#ifdef OHOS_ENABLE_PARAMETER + static CachedHandle sigchain_procmask_handle = NULL; + if (sigchain_procmask_handle == NULL) { + sigchain_procmask_handle = CachedParameterCreate(param_name, "false"); + } + char *param_value = CachedParameterGet(sigchain_procmask_handle); + if (param_value != NULL) { + if (strcmp(param_value, "true") == 0) { + return true; + } + } +#endif + return false; +} + +int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict old) +{ + int r = 0; + if (set && get_sigchain_mask_enable()) { + sigset_t tmpset = *set; + intercept_sigprocmask(how, &tmpset); + const sigset_t *new_set_ptr = &tmpset; + r = pthread_sigmask(how, new_set_ptr, old); + } else { + r = pthread_sigmask(how, set, old); + } + if (!r) return r; + errno = r; + return -1; +}