1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <setjmp.h>
18 #include <signal.h>
19
20 #include "berberis/ndk_program_tests/scoped_sigaction.h"
21
22 namespace {
23
FuncWithLongJump(jmp_buf buf)24 void FuncWithLongJump(jmp_buf buf) {
25 longjmp(buf, 1);
26 }
27
TEST(SetJmp,Jmp)28 TEST(SetJmp, Jmp) {
29 jmp_buf buf;
30 int value = setjmp(buf);
31 if (value == 0) {
32 FuncWithLongJump(buf);
33 FAIL();
34 }
35 ASSERT_EQ(value, 1);
36 }
37
38 jmp_buf g_jmp_buf;
39 bool g_wrapper_called;
40
LongjmpHandler(int)41 void LongjmpHandler(int) {
42 longjmp(g_jmp_buf, 1);
43 }
44
WrapperHandler(int)45 void WrapperHandler(int) {
46 g_wrapper_called = true;
47 struct sigaction sa {};
48 sigemptyset(&sa.sa_mask);
49 sa.sa_handler = LongjmpHandler;
50 ScopedSigaction scoped_sa(SIGXCPU, &sa);
51
52 int value = setjmp(g_jmp_buf);
53 if (value == 0) {
54 raise(SIGXCPU);
55 FAIL();
56 }
57 ASSERT_EQ(value, 1);
58 }
59
TEST(SetJmp,JmpFromSignalHandler)60 TEST(SetJmp, JmpFromSignalHandler) {
61 g_wrapper_called = false;
62 // Before we do setjmp/longjmp we create a nested execution by invoking a wrapper handler. This
63 // way we ensure that nested executions are handled correctly.
64 struct sigaction sa {};
65 sigemptyset(&sa.sa_mask);
66 sa.sa_handler = WrapperHandler;
67 ScopedSigaction scoped_sa(SIGPWR, &sa);
68 raise(SIGPWR);
69 ASSERT_TRUE(g_wrapper_called);
70 }
71
72 } // namespace
73