| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // http://crbug.com/269623 | |
| 6 // http://openradar.appspot.com/14999594 | |
| 7 // | |
| 8 // When the default version of close used on Mac OS X fails with EINTR, the | |
| 9 // file descriptor is not in a deterministic state. It may have been closed, | |
| 10 // or it may not have been. This makes it impossible to gracefully recover | |
| 11 // from the error. If the close is retried after the FD has been closed, the | |
| 12 // subsequent close can report EBADF, or worse, it can close an unrelated FD | |
| 13 // opened by another thread. If the close is not retried after the FD has been | |
| 14 // left open, the FD is leaked. Neither of these are good options. | |
| 15 // | |
| 16 // Mac OS X provides an alternate version of close, close$NOCANCEL. This | |
| 17 // version will never fail with EINTR before the FD is actually closed. With | |
| 18 // this version, it is thus safe to call close without checking for EINTR (as | |
| 19 // the HANDLE_EINTR macro does) and not risk leaking the FD. In fact, mixing | |
| 20 // this verison of close with HANDLE_EINTR is hazardous. | |
| 21 // | |
| 22 // The $NOCANCEL variants of various system calls are activated by compiling | |
| 23 // with __DARWIN_NON_CANCELABLE, which prevents them from being pthread | |
| 24 // cancellation points. Rather than taking such a heavy-handed approach, this | |
| 25 // file implements an alternative: to use the $NOCANCEL variant of close (thus | |
| 26 // preventing it from being a pthread cancellation point) without affecting | |
| 27 // any other system calls. | |
| 28 // | |
| 29 // This file operates by providing a close function with the non-$NOCANCEL | |
| 30 // symbol name expected for the compilation environment as set by <unistd.h> | |
| 31 // and <sys/cdefs.h> (the DARWIN_ALIAS_C macro). That name is set by an asm | |
| 32 // label on the declaration of the close function, so the definition of that | |
| 33 // function receives that name. The function calls the $NOCANCEL variant, which | |
| 34 // is resolved from libsyscall. By linking with this version of close prior to | |
| 35 // the libsyscall version, close's implementation is overridden. | |
| 36 | |
| 37 #include <sys/cdefs.h> | |
| 38 #include <unistd.h> | |
| 39 | |
| 40 // If the non-cancelable variants of all system calls have already been | |
| 41 // chosen, do nothing. | |
| 42 #if !__DARWIN_NON_CANCELABLE | |
| 43 | |
| 44 extern "C" { | |
| 45 | |
| 46 #if !__DARWIN_ONLY_UNIX_CONFORMANCE | |
| 47 | |
| 48 // When there's a choice between UNIX2003 and pre-UNIX2003. There's no | |
| 49 // close$NOCANCEL symbol in this case, so use close$NOCANCEL$UNIX2003 as the | |
| 50 // implementation. It does the same thing that close$NOCANCEL would do. | |
| 51 #define close_implementation close$NOCANCEL$UNIX2003 | |
| 52 | |
| 53 #else // __DARWIN_ONLY_UNIX_CONFORMANCE | |
| 54 | |
| 55 // When only UNIX2003 is supported: | |
| 56 #define close_implementation close$NOCANCEL | |
| 57 | |
| 58 #endif | |
| 59 | |
| 60 int close_implementation(int fd); | |
| 61 | |
| 62 int close(int fd) { | |
| 63 return close_implementation(fd); | |
| 64 } | |
| 65 | |
| 66 #undef close_implementation | |
| 67 | |
| 68 } // extern "C" | |
| 69 | |
| 70 #endif // !__DARWIN_NON_CANCELABLE | |
| OLD | NEW |