1 // Copyright 2020 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <errno.h> 18 #ifndef dfatal 19 #include "aemu/base/logging/CLog.h" 20 #endif 21 22 namespace android { 23 namespace base { 24 25 // Set EINTR_WRAPPER_DEBUG to 1 to force the debug version of HANDLE_EINTR 26 // which will call eintrWrapperFatal() is the system call loops 27 // too many times, or 0 to get it to loop indefinitly. 28 // Mostly used for unit testing. 29 // If the macro is undefined, auto-detect the value based on NDEBUG. 30 #if !defined(EINTR_WRAPPER_DEBUG) 31 #ifdef NDEBUG 32 #define EINTR_WRAPPER_DEBUG 0 33 #else 34 #define EINTR_WRAPPER_DEBUG 1 35 #endif 36 #endif 37 38 // HANDLE_EINTR() is a macro used to handle EINTR return values when 39 // calling system calls like open() or read() on Posix systems. 40 // 41 // By default, this will loop indefinitly, retrying the call until 42 // the result is no longer -1/EINTR, except in debug mode, where a 43 // loop counter is actually used and to provoke a fatal error if there 44 // are too many loops. 45 // 46 // Usage example: 47 // int ret = HANDLE_EINTR(open("/some/file/path", O_RDONLY)); 48 // 49 // IMPORTANT: Do not use with the close() system call (use IGNORE_EINTR() 50 // instead). 51 // 52 // - On Linux, the file descriptor is always already closed when this 53 // function returns -1/EINTR, and calling it again with the same 54 // parameters risks closing another file descriptor open by another 55 // thread in parallel! 56 // 57 // - On OS X, whether the file descriptor is closed or not is pretty 58 // much random! It's better to leave the descriptor open than risk 59 // closing another one by mistake :( 60 // 61 #define MAX_EINTR_LOOP_COUNT 100 62 63 #ifdef _WIN32 64 #define HANDLE_EINTR(x) (x) 65 #elif EINTR_WRAPPER_DEBUG == 0 66 #define HANDLE_EINTR(x) \ 67 __extension__({ \ 68 __typeof__(x) eintr_wrapper_result; \ 69 do { \ 70 eintr_wrapper_result = (x); \ 71 } while (eintr_wrapper_result < 0 && errno == EINTR); \ 72 eintr_wrapper_result; \ 73 }) 74 #else // !_WIN32 && EINTR_WRAPPER_DEBUG 75 76 #define HANDLE_EINTR(x) \ 77 __extension__({ \ 78 __typeof__(x) eintr_wrapper_result; \ 79 int eintr_wrapper_loop_count = 0; \ 80 for (;;) { \ 81 eintr_wrapper_result = (x); \ 82 if (eintr_wrapper_result != -1 || errno != EINTR) break; \ 83 ++eintr_wrapper_loop_count; \ 84 if (eintr_wrapper_loop_count >= MAX_EINTR_LOOP_COUNT) \ 85 dfatal("Looping around EINTR too many times"); \ 86 }; \ 87 eintr_wrapper_result; \ 88 }) 89 #endif // !_WIN32 && EINTR_WRAPPER_DEBUG 90 91 // IGNORE_EINTR() is a macro used to perform a system call and ignore 92 // an EINTR result, i.e. it will return 0 instead of -1 if this occurs. 93 // This is mostly used with the close() system call, as described 94 // in the HANDLE_EINTR() documentation. 95 #ifdef _WIN32 96 #define IGNORE_EINTR(x) (x) 97 #else 98 #define IGNORE_EINTR(x) \ 99 __extension__({ \ 100 __typeof__(x) eintr_wrapper_result = (x); \ 101 if (eintr_wrapper_result == -1 && errno == EINTR) eintr_wrapper_result = 0; \ 102 eintr_wrapper_result; \ 103 }) 104 #endif 105 106 } // namespace base 107 } // namespace android 108