From 06650545dd1082821b86b2b49c60e7b841f8762f Mon Sep 17 00:00:00 2001 From: John Ralls Date: Mon, 7 Nov 2022 13:01:47 +0000 Subject: [PATCH] [Darwin] Use the non-cancelable variant of close(). --- glib/gstdio.c | 3 +++ glib/gstdioprivate.h | 31 ++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/glib/gstdio.c b/glib/gstdio.c index cd3c8b405..b35a0ec1c 100644 --- a/glib/gstdio.c +++ b/glib/gstdio.c @@ -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; } diff --git a/glib/gstdioprivate.h b/glib/gstdioprivate.h index ecc354ada..c9e7826eb 100644 --- a/glib/gstdioprivate.h +++ b/glib/gstdioprivate.h @@ -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 +#include +# 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__ */