Home | History | Annotate | Download | only in utils
      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