1 // Copyright 2014 The Android Open Source Project 2 // 3 // This software is licensed under the terms of the GNU General Public 4 // License version 2, as published by the Free Software Foundation, and 5 // may be copied, distributed, and modified under those terms. 6 // 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License for more details. 11 12 // Forces debug mode 13 #define EINTR_WRAPPER_DEBUG 1 14 15 #include "android/utils/eintr_wrapper.h" 16 17 #include <stdarg.h> 18 #include <setjmp.h> 19 20 #include "android/utils/panic.h" 21 22 #include <gtest/gtest.h> 23 24 // Loop counter used by several functions below. 25 static int loop_count = 0; 26 27 // This function returns the first time it is called, or -1/EINVAL 28 // otherwise. 29 static int return_einval_after_first_call(void) { 30 if (++loop_count == 1) 31 return 0; 32 33 errno = EINVAL; 34 return -1; 35 } 36 37 TEST(eintr_wrapper,NoLoopOnSuccess) { 38 loop_count = 0; 39 EXPECT_EQ(0, HANDLE_EINTR(return_einval_after_first_call())); 40 EXPECT_EQ(1, loop_count); 41 } 42 43 TEST(eintr_wrapper,NoLoopOnRegularError) { 44 loop_count = 0; 45 EXPECT_EQ(0, HANDLE_EINTR(return_einval_after_first_call())); 46 EXPECT_EQ(-1, HANDLE_EINTR(return_einval_after_first_call())); 47 EXPECT_EQ(EINVAL, errno); 48 EXPECT_EQ(2, loop_count); 49 } 50 51 static int always_return_eintr(void) { 52 loop_count++; 53 #ifdef _WIN32 54 // Win32 cannot generate EINTR. 55 return 0; 56 #else 57 errno = EINTR; 58 return -1; 59 #endif 60 } 61 62 TEST(eintr_wrapper,IgnoreEintr) { 63 loop_count = 0; 64 EXPECT_EQ(0, IGNORE_EINTR(always_return_eintr())); 65 EXPECT_EQ(1, loop_count); 66 } 67 68 #ifndef _WIN32 69 70 // This function loops 10 times around |loop_count|, while returning 71 // -1/errno. 72 static int loop_eintr_10(void) { 73 if (++loop_count < 10) { 74 errno = EINTR; 75 return -1; 76 } 77 return 0; 78 } 79 80 TEST(eintr_wrapper,LoopOnEintr) { 81 loop_count = 0; 82 EXPECT_EQ(0, HANDLE_EINTR(loop_eintr_10())); 83 EXPECT_EQ(10, loop_count); 84 } 85 86 // Implementation of a custom panic function used to detect that 87 // HANDLE_EINTR() called panic after too many loop iterations. 88 // Uses setjmp()/longjmp() since the panic handler must be 89 // __attribute__((noreturn)). 90 static jmp_buf panic_jumper; 91 static bool panic_called = false; 92 93 static void __attribute__((noreturn)) 94 my_panic_handler(const char*, va_list); 95 96 static void my_panic_handler(const char* fmt, va_list args) { 97 panic_called = true; 98 longjmp(panic_jumper, 1); 99 } 100 101 static int loop_eintr_200(void) { 102 if (++loop_count < 200) { 103 errno = EINTR; 104 return -1; 105 } 106 return 0; 107 } 108 109 TEST(eintr_wrapper,PanicOnTooManyLoops) { 110 loop_count = 0; 111 android_panic_registerHandler(my_panic_handler); 112 if (setjmp(panic_jumper) == 0) { 113 HANDLE_EINTR(loop_eintr_200()); 114 ASSERT_TRUE(0) << "HANDLE_EINTR() didn't panic!"; 115 } else { 116 EXPECT_EQ(true, panic_called); 117 EXPECT_EQ(MAX_EINTR_LOOP_COUNT, loop_count); 118 } 119 } 120 121 #endif // !_WIN32 122