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