[Darwin] Use the non-cancelable variant of close().

This commit is contained in:
John Ralls 2022-11-07 13:01:47 +00:00 committed by Philip Withnall
parent 483b6f2214
commit 06650545dd
2 changed files with 33 additions and 1 deletions

View File

@ -1795,6 +1795,9 @@ g_close (gint fd,
* https://bugzilla.gnome.org/show_bug.cgi?id=682819
* http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
* https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
*
* `close$NOCANCEL()` in gstdioprivate.h, on macOS, ensures that the fd is
* closed even if it did return EINTR.
*/
return TRUE;
}

View File

@ -68,7 +68,36 @@ int g_win32_fstat (int fd,
GWin32PrivateStat *buf);
#endif
/* The POSIX standard specifies that if close() fails with EINTR the
* file descriptor may or may not be in fact closed. Since another
* thread might have already reused the FD if it was in fact closed
* either a test of FD to ensure that it's closed nor a second
* call to close() may indicate the wrong FD, so the error must be
* ignored.
*
* However, since Mac OS X 10.5 (Leopard) Apple provdes a hidden
* implementation of close that doesn't allow another thread
* to cancel the close so it never fails with EINTR.
*
* The official way to enable this is to set __DARWIN_NON_CANCELABLE
* in the build, but that applies to all system calls, not just
* close(). Following Chromium's example (see
* https://chromium.googlesource.com/chromium/src/base/+/refs/heads/main/mac/close_nocancel.cc )
* we choose to expose and use the hidden close variant only.
*/
#ifdef __APPLE__
#include <sys/cdefs.h>
#include <unistd.h>
# if !__DARWIN_NON_CANCELABLE
# if !__DARWIN_ONLY_UNIX_CONFORMANCE
# define close close$NOCANCEL$UNIX2003
int close$NOCANCEL$UNIX2003 (int fd);
# else
# define close close$NOCANCEL
int close$NOCANCEL (int fd);
# endif
# endif
#endif
G_END_DECLS
#endif /* __G_STDIOPRIVATE_H__ */