Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions subprojects/libglnx/glnx-backports.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,78 @@ _glnx_strv_equal (const gchar * const *strv1,
}
#endif

#if !GLIB_CHECK_VERSION(2, 76, 0)
gboolean
_glnx_close (gint fd,
GError **error)
{
int res;

/* Important: if @error is NULL, we must not do anything that is
* not async-signal-safe.
*/
res = close (fd);

if (res == -1)
{
int errsv = errno;

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...
*
* close_func_with_invalid_fds() in gspawn.c has similar logic.
*
* 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
*
* `close$NOCANCEL()` in gstdioprivate.h, on macOS, ensures that the fd is
* closed even if it did return EINTR.
*/
return TRUE;
}

if (error)
{
g_set_error_literal (error, G_FILE_ERROR,
g_file_error_from_errno (errsv),
g_strerror (errsv));
}

if (errsv == EBADF)
{
/* There is a bug. Fail an assertion. Note that this function is supposed to be
* async-signal-safe, but in case an assertion fails, all bets are already off. */
if (fd >= 0)
{
/* Closing an non-negative, invalid file descriptor is a bug. The bug is
* not necessarily in the caller of _glnx_close(), but somebody else
* might have wrongly closed fd. In any case, there is a serious bug
* somewhere. */
g_critical ("_glnx_close(fd:%d) failed with EBADF. The tracking of file descriptors got messed up", fd);
}
else
{
/* Closing a negative "file descriptor" is less problematic. It's still a nonsensical action
* from the caller. Assert against that too. */
g_critical ("_glnx_close(fd:%d) failed with EBADF. This is not a valid file descriptor", fd);
}
}

errno = errsv;

return FALSE;
}

return TRUE;
}
#endif

#if !GLIB_CHECK_VERSION(2, 80, 0)
/* This function is called between fork() and exec() and hence must be
* async-signal-safe (see signal-safety(7)). */
Expand Down
46 changes: 43 additions & 3 deletions subprojects/libglnx/glnx-backports.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include <string.h>

#include <glib-unix.h>
#include <glib/gstdio.h>
#include <gio/gio.h>

G_BEGIN_DECLS
Expand All @@ -52,6 +54,34 @@ G_BEGIN_DECLS
} G_STMT_END
#endif

#if !GLIB_CHECK_VERSION(2, 76, 0)
gboolean _glnx_close (gint fd,
GError **error);
#else
#define _glnx_close g_close
#endif

#if !GLIB_CHECK_VERSION(2, 76, 0)
static inline gboolean
g_clear_fd (int *fd_ptr,
GError **error)
{
int fd = *fd_ptr;

*fd_ptr = -1;

if (fd < 0)
return TRUE;

/* Suppress "Not available before" warning */
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/* This importantly calls _glnx_close to always get async-signal-safe if
* error == NULL */
return _glnx_close (fd, error);
G_GNUC_END_IGNORE_DEPRECATIONS
}
#endif

#if !GLIB_CHECK_VERSION(2, 40, 0)
#define g_info(...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__)
#endif
Expand Down Expand Up @@ -80,6 +110,10 @@ gboolean glnx_set_object (GObject **object_ptr,
#define G_OPTION_FLAG_NONE ((GOptionFlags) 0)
#endif

#ifndef G_PID_FORMAT /* added in 2.50 */
#define G_PID_FORMAT "i"
#endif

#if !GLIB_CHECK_VERSION(2, 60, 0)
#define g_strv_equal _glnx_strv_equal
gboolean _glnx_strv_equal (const gchar * const *strv1,
Expand Down Expand Up @@ -125,16 +159,22 @@ _glnx_memdup2 (gconstpointer mem,
(((a) > (b) ? (a) - (b) : (b) - (a)) < (epsilon))
#endif

#if !GLIB_CHECK_VERSION(2, 70, 0)
#define g_steal_fd _glnx_steal_fd
static inline int
_glnx_steal_fd (int *fdp)
{
#if GLIB_CHECK_VERSION(2, 70, 0)
/* Allow it to be used without deprecation warnings, even if the target
* GLib version is older */
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
return g_steal_fd (fdp);
G_GNUC_END_IGNORE_DEPRECATIONS
#else
int fd = *fdp;
*fdp = -1;
return fd;
}
#endif
}
#define g_steal_fd _glnx_steal_fd

#if !GLIB_CHECK_VERSION(2, 74, 0)
#define G_APPLICATION_DEFAULT_FLAGS ((GApplicationFlags) 0)
Expand Down
Loading
Loading