1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This provides a wrapper around system calls which may be interrupted by a
6 // signal and return EINTR. See man 7 signal.
7 // To prevent long-lasting loops (which would likely be a bug, such as a signal
8 // that should be masked) to go unnoticed, there is a limit after which the
9 // caller will nonetheless see an EINTR in Debug builds.
10 //
11 // On Windows and Fuchsia, this wrapper does nothing because there are no
12 // signals.
13 //
14 // Don't wrap close calls in WrapEINTR. Use IGNORE_EINTR macro if the return
15 // value of close is significant. See http://crbug.com/269623.
16 
17 #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_EINTR_WRAPPER_H_
18 #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_EINTR_WRAPPER_H_
19 
20 #include "build/build_config.h"
21 
22 #if BUILDFLAG(IS_POSIX)
23 #include <cerrno>
24 #include <utility>
25 #endif
26 
27 namespace partition_alloc {
28 #if BUILDFLAG(IS_POSIX)
29 
30 template <typename Fn>
WrapEINTR(Fn fn)31 inline auto WrapEINTR(Fn fn) {
32   return [fn](auto&&... args) {
33     int out = -1;
34 #if defined(NDEBUG)
35     while (true)
36 #else
37     for (int retry_count = 0; retry_count < 100; ++retry_count)
38 #endif
39     {
40       out = fn(std::forward<decltype(args)>(args)...);
41       if (out != -1 || errno != EINTR) {
42         return out;
43       }
44     }
45     return out;
46   };
47 }
48 
49 #else  // !BUILDFLAG(IS_POSIX)
50 
51 template <typename Fn>
52 inline auto WrapEINTR(Fn fn) {
53   return fn;
54 }
55 
56 #endif  // !BUILDFLAG(IS_POSIX)
57 
58 }  // namespace partition_alloc
59 
60 #endif  // PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_EINTR_WRAPPER_H_
61