[glib/th/gspawn-no-safe-close: 1/2] gstdio: make g_close() async-signal-safe under certain conditions




commit 3ed7f4d1ed7e49b5d38d837d3edba69f5b7eaaf6
Author: Thomas Haller <thaller redhat com>
Date:   Tue Oct 18 09:07:35 2022 +0200

    gstdio: make g_close() async-signal-safe under certain conditions
    
    g_close() does something useful. It is not trivial to get EINTR handling of
    close() right, in a portable manner. g_close() abstracts this.
    
    We should allow glib users to use the function even in async-signal-safe
    contexts, at least if the user heeds the caveat about GError and take care
    not to fail assertions.

 glib/gstdio.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
---
diff --git a/glib/gstdio.c b/glib/gstdio.c
index 22d1159ce5..7fe7b32ed8 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
@@ -1759,6 +1760,9 @@ g_utime (const gchar    *filename,
  *
  * It is a bug to call this function with an invalid file descriptor.
  *
+ * Since 2.76, this function is guaranteed to be async-signal-safe if (and only
+ * if) @error is %NULL and @fd is a valid open file descriptor.
+ *
  * Returns: %TRUE on success, %FALSE if there was an error.
  *
  * Since: 2.36
@@ -1769,6 +1773,9 @@ g_close (gint       fd,
 {
   int res;
 
+  /* Important: if @error is NULL, we must not do anything that is
+   * not async-signal-safe.
+   */
   res = close (fd);
 
   if (res == -1)
@@ -1790,12 +1797,17 @@ g_close (gint       fd,
           return TRUE;
         }
 
-      g_set_error_literal (error, G_FILE_ERROR,
-                           g_file_error_from_errno (errsv),
-                           g_strerror (errsv));
+      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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]