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 #ifndef ANDROID_UTILS_EINTR_WRAPPER_H 12 #define ANDROID_UTILS_EINTR_WRAPPER_H 13 14 #include <errno.h> 15 16 #include "android/utils/compiler.h" 17 18 ANDROID_BEGIN_HEADER 19 20 // Set EINTR_WRAPPER_DEBUG to 1 to force the debug version of HANDLE_EINTR 21 // which will call android_eintr_wrapper_fatal() is the system call loops 22 // too many times, or 0 to get it to loop indefinitly. 23 // Mostly used for unit testing. 24 // If the macro is undefined, auto-detect the value based on NDEBUG. 25 #if !defined(EINTR_WRAPPER_DEBUG) 26 # ifdef NDEBUG 27 # define EINTER_WRAPPER_DEBUG 0 28 # else 29 # define EINTR_WRAPPER_DEBUG 1 30 # endif 31 #endif 32 33 // HANDLE_EINTR() is a macro used to handle EINTR return values when 34 // calling system calls like open() or read() on Posix systems. 35 // 36 // By default, this will loop indefinitly, retrying the call until 37 // the result is no longer -1/EINTR, except in debug mode, where a 38 // loop counter is actually used and to provoke a fatal error if there 39 // are too many loops. 40 // 41 // Usage example: 42 // int ret = HANDLE_EINTR(open("/some/file/path", O_RDONLY)); 43 // 44 // IMPORTANT: Do not use with the close() system call (use IGNORE_EINTR() 45 // instead). 46 // 47 // - On Linux, the file descriptor is always already closed when this 48 // function returns -1/EINTR, and calling it again with the same 49 // parameters risks closing another file descriptor open by another 50 // thread in parallel! 51 // 52 // - On OS X, whether the file descriptor is closed or not is pretty 53 // much random! It's better to leave the descriptor open than risk 54 // closing another one by mistake :( 55 // 56 #ifdef _WIN32 57 # define HANDLE_EINTR(x) (x) 58 #elif EINTR_WRAPPER_DEBUG == 0 59 # define HANDLE_EINTR(x) \ 60 __extension__ ({ \ 61 __typeof__(x) eintr_wrapper_result; \ 62 do { \ 63 eintr_wrapper_result = (x); \ 64 } while (eintr_wrapper_result < 0 && errno == EINTR); \ 65 eintr_wrapper_result; \ 66 }) 67 #else // !_WIN32 && EINTR_WRAPPER_DEBUG 68 69 # define MAX_EINTR_LOOP_COUNT 100 70 71 # define HANDLE_EINTR(x) \ 72 __extension__ ({ \ 73 __typeof__(x) eintr_wrapper_result; \ 74 int eintr_wrapper_loop_count = 0; \ 75 for (;;) { \ 76 eintr_wrapper_result = (x); \ 77 if (eintr_wrapper_result != -1 || errno != EINTR) \ 78 break; \ 79 if (++eintr_wrapper_loop_count >= MAX_EINTR_LOOP_COUNT) { \ 80 android_eintr_wrapper_fatal( \ 81 __FILE__,__LINE__,__PRETTY_FUNCTION__,#x); \ 82 } \ 83 }; \ 84 eintr_wrapper_result; \ 85 }) 86 #endif // !_WIN32 && EINTR_WRAPPER_DEBUG 87 88 // IGNORE_EINTR() is a macro used to perform a system call and ignore 89 // an EINTR result, i.e. it will return 0 instead of -1 if this occurs. 90 // This is mostly used with the close() system call, as described 91 // in the HANDLE_EINTR() documentation. 92 #ifdef _WIN32 93 # define IGNORE_EINTR(x) (x) 94 #else 95 # define IGNORE_EINTR(x) \ 96 __extension__ ({ \ 97 __typeof__(x) eintr_wrapper_result = (x); \ 98 if (eintr_wrapper_result == -1 && errno == EINTR) \ 99 eintr_wrapper_result = 0; \ 100 eintr_wrapper_result; \ 101 }) 102 #endif 103 104 #ifndef _WIN32 105 // This function is called in debug mode only when a system call wrapped 106 // by HANDLE_EINTR() failed more than MAX_EINTR_LOOP_COUNT times. 107 // |file| is the source file location. 108 // |lineno| is the line number in the source file. 109 // |function| is the name of the function, or NULL if not available. 110 // |call| is a string describing the system call that failed. 111 void __attribute__((noreturn)) android_eintr_wrapper_fatal( 112 const char* file, 113 long lineno, 114 const char* function, 115 const char* call); 116 #endif // !_WIN32 117 118 ANDROID_END_HEADER 119 120 #endif // ANDROID_UTILS_EINTR_WRAPPER_H 121