setjmp_test.cpp revision e323e99ffbf9e508e74a261f1075433f5a81677f
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 */ 16 17#include <gtest/gtest.h> 18 19#include <setjmp.h> 20#include <stdlib.h> 21 22TEST(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} 32 33TEST(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} 43 44TEST(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} 54 55TEST(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} 65 66static sigset_t SigSetOf(int signal) { 67 sigset_t ss; 68 sigemptyset(&ss); 69 sigaddset(&ss, signal); 70 return ss; 71} 72 73TEST(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} 91 92TEST(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); 117} 118 119TEST(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); 136} 137 138TEST(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); 155} 156