[glib/th/gspawn-no-safe-close: 10/11] gutilsprivate: add internal _g_safe_close() wrapper to replace g_close()/close()




commit 1df4c02ef484bad621dbacc74d3c4119597a1b17
Author: Thomas Haller <thaller redhat com>
Date:   Tue Oct 18 08:42:08 2022 +0200

    gutilsprivate: add internal _g_safe_close() wrapper to replace g_close()/close()
    
    1) From internal code, we should never use close() directly, because
    
      - we want to assert against EBADF to catch bugs (g_close() does that).
      - we want to handle EINTR (g_close() does that, even if it currently
        just ignores it).
    
    2) on the upside, g_close() gets most these things right. But from internal code,
    we should still not use g_close() directly, because
    
      - the API of g_close() returns errors, which wrongly suggests that the
        user should do something about those errors. They almost always should
        not, see `man 2 close`.
      - g_error() changes errno, which is usually undesirable, in particular
        because we don't want to handle errors.
      - g_close() is only async-signal-safe under certain conditions. It
        means, we need to be careful where (or how) we use g_close().
    
    Add an internal _g_safe_close() wrapper, to get all these things right.
    This is to replace close() and g_close().

 glib/gutils.c        | 29 +++++++++++++++++++++++++++++
 glib/gutilsprivate.h |  2 ++
 2 files changed, 31 insertions(+)
---
diff --git a/glib/gutils.c b/glib/gutils.c
index 78ccd61214..4ad92da584 100644
--- a/glib/gutils.c
+++ b/glib/gutils.c
@@ -3246,3 +3246,32 @@ g_abort (void)
   ExitProcess (127);
 }
 #endif
+
+/**
+ * _g_safe_close:
+ * fd: the file descriptor to close.
+ *
+ * This is a safe wrapper around g_close() and close(). From internal code,
+ * in almost all cases this function should be used instead of g_close()
+ * and close().
+ *
+ * This is guaranteed to be async-signal-safe (except assertion failures), so it
+ * can be used from a signal handler or between fork and exec.
+ *
+ * As `man 2 close` documents, there isn't much you can do about errors anyway.
+ * _g_safe_close() enforces this by returning no result.
+ *
+ * The function preserves errno.
+ *
+ * This function just calls g_close(), so it handles EINTR (currently by ignoring
+ * it) and EBADF (by asserting).
+ */
+void
+_g_safe_close (int fd)
+{
+  int errsv;
+
+  errsv = errno;
+  g_close (fd, NULL);
+  errno = errsv;
+}
diff --git a/glib/gutilsprivate.h b/glib/gutilsprivate.h
index 77bed4e87b..2359cf0794 100644
--- a/glib/gutilsprivate.h
+++ b/glib/gutilsprivate.h
@@ -54,6 +54,8 @@ g_nearest_pow (gsize num)
   return n + 1;
 }
 
+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]