Home | History | Annotate | Download | only in base
      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 
     19 namespace android {
     20 namespace 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