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