[glib/th/gspawn-no-safe-close: 2/4] gutilsprivate: add safe_close() and safe_close_with_error() helper
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/th/gspawn-no-safe-close: 2/4] gutilsprivate: add safe_close() and safe_close_with_error() helper
- Date: Tue, 18 Oct 2022 07:01:06 +0000 (UTC)
commit 152995a6b02866e1e7e2267439270df3987a5e74
Author: Thomas Haller <thaller redhat com>
Date: Tue Oct 18 08:42:08 2022 +0200
gutilsprivate: add safe_close() and safe_close_with_error() helper
glib/gutils.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
glib/gutilsprivate.h | 4 +++
2 files changed, 96 insertions(+)
---
diff --git a/glib/gutils.c b/glib/gutils.c
index 78ccd61214..a2c09986ab 100644
--- a/glib/gutils.c
+++ b/glib/gutils.c
@@ -3246,3 +3246,95 @@ g_abort (void)
ExitProcess (127);
}
#endif
+
+/**
+ * _g_safe_close_with_error:
+ * fd: the file descriptor to close.
+ *
+ * This function is async-signal-safe (except assertion failures), so it can be used from a
+ * signal handler or between fork and exec.
+ *
+ * While this function returns an error result, in most cases there isn't
+ * much you want to do about it. See `man 3 close`. Probably you should use
+ * _g_safe_close() wrapper instead.
+ *
+ * This handles EINTR internally (currently by ignoring it and signaling success).
+ *
+ * It asserts against EBADF (which itself is not async-signal-safe, but in case
+ * of an assertion failure, all bets are already off).
+ *
+ * The function may change errno.
+ *
+ * Returns: zero on success, or a negative errno.
+ */
+int
+_g_safe_close_with_error (int fd)
+{
+ int errsv;
+ int r;
+
+ r = close (fd);
+
+ if (r == 0)
+ return 0;
+
+ 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...
+ *
+ * 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 0;
+ }
+
+ if (errsv == EBADF)
+ {
+ /* There is a bug. Fail and assertion. Note that this function is supposed to be
+ * async-signal-safe, but in case an assertion fails, that is not the case! */
+ if (fd >= 0)
+ {
+ /* Closing an non-negative, invalid file descriptor is a bug. The bug is
+ * not necessarily in the caller of g_close(), but somebody else
+ * might have wrongly closed fd. In any case, there is a serious bug
+ * somewhere. */
+ g_critical ("g_close(fd:%d) failed with EBADF. The tracking of file descriptors got messed up",
fd);
+ }
+ else
+ {
+ g_critical ("g_close(fd:%d) failed with EBADF. This is not a valid file descriptor", fd);
+ }
+ }
+
+ return -errsv;
+}
+
+/**
+ * _g_safe_close:
+ * fd: the file descriptor to close.
+ *
+ * This wraps _g_safe_close_with_error(), so everything said there applies.
+ * Additionally:
+ *
+ * This function returns no error. In most cases, there is nothing to handle about
+ * failures of close (see `man 3 close`). In most cases, use _g_safe_close() instead
+ * of _g_safe_close_with_error().
+ *
+ * The function promises not to change errno.
+ */
+void
+_g_safe_close (int fd)
+{
+ int errsv;
+
+ errsv = errno;
+ _g_safe_close_with_error (fd);
+ errno = errsv;
+}
diff --git a/glib/gutilsprivate.h b/glib/gutilsprivate.h
index 77bed4e87b..a0ae28dfd4 100644
--- a/glib/gutilsprivate.h
+++ b/glib/gutilsprivate.h
@@ -54,6 +54,10 @@ g_nearest_pow (gsize num)
return n + 1;
}
+int _g_safe_close_with_error (int fd);
+
+void _g_safe_close (int fd);
+
G_END_DECLS
#endif /* __G_UTILS_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]