未验证 提交 0030a18d 编写于 作者: O openharmony_ci 提交者: Gitee

!788 SigChain功能实现

Merge pull request !788 from dhy308/release_sigchain_0113
/*
* 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
# 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}" ]
}
}
/*
* 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 <sigchain.h>
#include <wchar.h>
#include <stdlib.h>
#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
/*
* 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 <sigchain.h>
#include <wchar.h>
#include <stdlib.h>
#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
/*
* 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 <sigchain.h>
#include <signal.h>
#include <wchar.h>
#include <stdlib.h>
#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
/*
* 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 <sigchain.h>
#include <signal.h>
#include <wchar.h>
#include <stdlib.h>
#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
/*
* 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 <sigchain.h>
#include <signal.h>
#include <wchar.h>
#include <stdlib.h>
#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
/*
* 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 <sigchain.h>
#include <wchar.h>
#include <stdlib.h>
#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
# 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",
]
......@@ -29,4 +29,5 @@ functionalext_list = [
"sched:functionalext_sched_test",
"unittest:functionalext_unittest_test",
"legacy:functionalext_legacy_test",
"sigchain:functionalext_sigchain_test",
]
......@@ -233,6 +233,10 @@ template("test_unittest") {
}
}
}
if (target_dir == "functionalext/sigchain") {
include_dirs += [ "//${musl_base_dir}/include" ]
}
}
}
......
......@@ -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;
......
......@@ -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 = [
......
/*
* 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 <signal.h>
#include <stdint.h>
#include <stdbool.h>
#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
/*
* 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 <sigchain.h>
#include <locale.h>
#include <pthread.h>
#include <errno.h>
#include <threads.h>
#include <hilog_adapter.h>
#include <stdlib.h>
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;
}
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#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);
#include <signal.h>
#include <errno.h>
#include <sigchain.h>
#include <stddef.h>
#include <hilog_adapter.h>
#include <string.h>
#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;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册