diff --git a/glib/gspawn.c b/glib/gspawn.c index 4e029eedf..4f4c55d99 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -162,8 +162,6 @@ extern char **environ; */ -static gint safe_close (gint fd); - static gint g_execute (const gchar *file, gchar **argv, gchar **argv_buffer, @@ -267,11 +265,9 @@ close_and_invalidate (gint *fd) { if (*fd < 0) return; - else - { - safe_close (*fd); - *fd = -1; - } + + g_close (*fd, NULL); + *fd = -1; } /* Some versions of OS X define READ_OK in public headers */ @@ -1338,27 +1334,13 @@ dupfd_cloexec (int old_fd, int new_fd_min) return fd; } -/* This function is called between fork() and exec() and hence must be - * async-signal-safe (see signal-safety(7)). */ -static gint -safe_close (gint fd) -{ - gint ret; - - do - ret = close (fd); - while (ret < 0 && errno == EINTR); - - return ret; -} - /* This function is called between fork() and exec() and hence must be * async-signal-safe (see signal-safety(7)). */ G_GNUC_UNUSED static int close_func (void *data, int fd) { if (fd >= GPOINTER_TO_INT (data)) - (void) safe_close (fd); + g_close (fd, NULL); return 0; } @@ -1453,7 +1435,7 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) } } - safe_close (dir_fd); + g_close (dir_fd, NULL); return res; } diff --git a/glib/gstdio.c b/glib/gstdio.c index f2d58134e..fa291c287 100644 --- a/glib/gstdio.c +++ b/glib/gstdio.c @@ -1749,8 +1749,9 @@ g_utime (const gchar *filename, * @fd: A file descriptor * @error: a #GError * - * This wraps the close() call; in case of error, %errno will be + * This wraps the close() call. In case of error, %errno will be * preserved, but the error will also be stored as a #GError in @error. + * In case of success, %errno is undefined. * * Besides using #GError, there is another major reason to prefer this * function over the call provided by the system; on Unix, it will @@ -1766,24 +1767,38 @@ g_close (gint fd, GError **error) { int res; - res = close (fd); - /* Just ignore EINTR for now; a retry loop is the wrong thing to do - * on Linux at least. Anyone who wants to add a conditional check - * for e.g. HP-UX is welcome to do so later... - * - * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html - * 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 + + /* Important: if @error is NULL, we must not do anything that is + * not async-signal-safe. */ - if (G_UNLIKELY (res == -1 && errno == EINTR)) - return TRUE; - else if (res == -1) + res = close (fd); + + if (res == -1) { int errsv = errno; - g_set_error_literal (error, G_FILE_ERROR, - g_file_error_from_errno (errsv), - g_strerror (errsv)); + + if (errsv == EINTR) + { + /* Just ignore EINTR for now; a retry loop is the wrong thing to do + * on Linux at least. Anyone who wants to add a conditional check + * for e.g. HP-UX is welcome to do so later... + * + * https://lwn.net/Articles/576478/ + * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html + * 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 + */ + return TRUE; + } + + if (error) + { + g_set_error_literal (error, G_FILE_ERROR, + g_file_error_from_errno (errsv), + g_strerror (errsv)); + } + errno = errsv; return FALSE; }