restore sigprocmask in setjmp/longjmp test.
[android-sdk/platform-bionic.git] / tests / setjmp_test.cpp
1 /*
2  * Copyright (C) 2014 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  */
17 #include <gtest/gtest.h>
19 #include <setjmp.h>
20 #include <stdlib.h>
22 TEST(setjmp, setjmp_smoke) {
23   int value;
24   jmp_buf jb;
25   if ((value = setjmp(jb)) == 0) {
26     longjmp(jb, 123);
27     FAIL(); // Unreachable.
28   } else {
29     ASSERT_EQ(123, value);
30   }
31 }
33 TEST(setjmp, _setjmp_smoke) {
34   int value;
35   jmp_buf jb;
36   if ((value = _setjmp(jb)) == 0) {
37     _longjmp(jb, 456);
38     FAIL(); // Unreachable.
39   } else {
40     ASSERT_EQ(456, value);
41   }
42 }
44 TEST(setjmp, sigsetjmp_0_smoke) {
45   int value;
46   sigjmp_buf jb;
47   if ((value = sigsetjmp(jb, 0)) == 0) {
48     siglongjmp(jb, 789);
49     FAIL(); // Unreachable.
50   } else {
51     ASSERT_EQ(789, value);
52   }
53 }
55 TEST(setjmp, sigsetjmp_1_smoke) {
56   int value;
57   sigjmp_buf jb;
58   if ((value = sigsetjmp(jb, 0)) == 0) {
59     siglongjmp(jb, 0xabc);
60     FAIL(); // Unreachable.
61   } else {
62     ASSERT_EQ(0xabc, value);
63   }
64 }
66 static sigset_t SigSetOf(int signal) {
67   sigset_t ss;
68   sigemptyset(&ss);
69   sigaddset(&ss, signal);
70   return ss;
71 }
73 TEST(setjmp, _setjmp_signal_mask) {
74   // _setjmp/_longjmp do not save/restore the signal mask.
75   sigset_t ss1(SigSetOf(SIGUSR1));
76   sigset_t ss2(SigSetOf(SIGUSR2));
77   sigset_t original_set;
78   sigprocmask(SIG_SETMASK, &ss1, &original_set);
79   jmp_buf jb;
80   if (_setjmp(jb) == 0) {
81     sigprocmask(SIG_SETMASK, &ss2, NULL);
82     _longjmp(jb, 1);
83     FAIL(); // Unreachable.
84   } else {
85     sigset_t ss;
86     sigprocmask(SIG_SETMASK, NULL, &ss);
87     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
88   }
89   sigprocmask(SIG_SETMASK, &original_set, NULL);
90 }
92 TEST(setjmp, setjmp_signal_mask) {
93   // setjmp/longjmp do save/restore the signal mask on bionic, but not on glibc.
94   // This is a BSD versus System V historical accident. POSIX leaves the
95   // behavior unspecified, so any code that cares needs to use sigsetjmp.
96   sigset_t ss1(SigSetOf(SIGUSR1));
97   sigset_t ss2(SigSetOf(SIGUSR2));
98   sigset_t original_set;
99   sigprocmask(SIG_SETMASK, &ss1, &original_set);
100   jmp_buf jb;
101   if (setjmp(jb) == 0) {
102     sigprocmask(SIG_SETMASK, &ss2, NULL);
103     longjmp(jb, 1);
104     FAIL(); // Unreachable.
105   } else {
106     sigset_t ss;
107     sigprocmask(SIG_SETMASK, NULL, &ss);
108 #if defined(__BIONIC__)
109     // bionic behaves like BSD and does save/restore the signal mask.
110     EXPECT_TRUE(sigismember(&ss, SIGUSR1));
111 #else
112     // glibc behaves like System V and doesn't save/restore the signal mask.
113     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
114 #endif
115   }
116   sigprocmask(SIG_SETMASK, &original_set, NULL);
119 TEST(setjmp, sigsetjmp_0_signal_mask) {
120   // sigsetjmp(0)/siglongjmp do not save/restore the signal mask.
121   sigset_t ss1(SigSetOf(SIGUSR1));
122   sigset_t ss2(SigSetOf(SIGUSR2));
123   sigset_t original_set;
124   sigprocmask(SIG_SETMASK, &ss1, &original_set);
125   sigjmp_buf sjb;
126   if (sigsetjmp(sjb, 0) == 0) {
127     sigprocmask(SIG_SETMASK, &ss2, NULL);
128     siglongjmp(sjb, 1);
129     FAIL(); // Unreachable.
130   } else {
131     sigset_t ss;
132     sigprocmask(SIG_SETMASK, NULL, &ss);
133     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
134   }
135   sigprocmask(SIG_SETMASK, &original_set, NULL);
138 TEST(setjmp, sigsetjmp_1_signal_mask) {
139   // sigsetjmp(1)/siglongjmp does save/restore the signal mask.
140   sigset_t ss1(SigSetOf(SIGUSR1));
141   sigset_t ss2(SigSetOf(SIGUSR2));
142   sigset_t original_set;
143   sigprocmask(SIG_SETMASK, &ss1, &original_set);
144   sigjmp_buf sjb;
145   if (sigsetjmp(sjb, 1) == 0) {
146     sigprocmask(SIG_SETMASK, &ss2, NULL);
147     siglongjmp(sjb, 1);
148     FAIL(); // Unreachable.
149   } else {
150     sigset_t ss;
151     sigprocmask(SIG_SETMASK, NULL, &ss);
152     EXPECT_TRUE(sigismember(&ss, SIGUSR1));
153   }
154   sigprocmask(SIG_SETMASK, &original_set, NULL);