[glib] g_unix_set_fd_nonblocking: New API to control file descriptor blocking state



commit ed37970a0405b5681bcd6449d4dc1b4f9080c4fa
Author: Colin Walters <walters verbum org>
Date:   Tue May 3 09:52:10 2011 -0400

    g_unix_set_fd_nonblocking: New API to control file descriptor blocking state
    
    And use it in relevant places in GLib.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=649225

 gio/gcancellable.c |   27 +++++----------------------
 gio/gsocket.c      |   17 ++++++++---------
 glib/glib-unix.c   |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/glib-unix.h   |    4 ++++
 glib/glib.symbols  |    1 +
 glib/gmain.c       |    2 +-
 6 files changed, 69 insertions(+), 32 deletions(-)
---
diff --git a/gio/gcancellable.c b/gio/gcancellable.c
index c37baff..32f5081 100644
--- a/gio/gcancellable.c
+++ b/gio/gcancellable.c
@@ -21,11 +21,10 @@
  */
 
 #include "config.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#include "glib.h"
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
 #endif
-#include <errno.h>
-#include <fcntl.h>
 #include <gioerror.h>
 #ifdef G_OS_WIN32
 #include <windows.h>
@@ -193,22 +192,6 @@ g_cancellable_class_init (GCancellableClass *klass)
 }
 
 #ifndef G_OS_WIN32
-static void
-set_fd_nonblocking (int fd)
-{
-#ifdef F_GETFL
-  glong fcntl_flags;
-  fcntl_flags = fcntl (fd, F_GETFL);
-
-#ifdef O_NONBLOCK
-  fcntl_flags |= O_NONBLOCK;
-#else
-  fcntl_flags |= O_NDELAY;
-#endif
-
-  fcntl (fd, F_SETFL, fcntl_flags);
-#endif
-}
 
 static void
 set_fd_close_exec (int fd)
@@ -235,8 +218,8 @@ g_cancellable_open_pipe (GCancellable *cancellable)
       /* Make them nonblocking, just to be sure we don't block
        * on errors and stuff
        */
-      set_fd_nonblocking (priv->cancel_pipe[0]);
-      set_fd_nonblocking (priv->cancel_pipe[1]);
+      g_unix_set_fd_nonblocking (priv->cancel_pipe[0], TRUE, NULL);
+      g_unix_set_fd_nonblocking (priv->cancel_pipe[1], TRUE, NULL);
       set_fd_close_exec (priv->cancel_pipe[0]);
       set_fd_close_exec (priv->cancel_pipe[1]);
       
diff --git a/gio/gsocket.c b/gio/gsocket.c
index d0219c1..4b5f18a 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -29,6 +29,10 @@
 
 #include "gsocket.h"
 
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
+
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
@@ -240,22 +244,17 @@ static void
 set_fd_nonblocking (int fd)
 {
 #ifndef G_OS_WIN32
-  glong arg;
+  GError *error = NULL;
 #else
   gulong arg;
 #endif
 
 #ifndef G_OS_WIN32
-  if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
+  if (!g_unix_set_fd_nonblocking (fd, TRUE, &error))
     {
-      g_warning ("Error getting socket status flags: %s", socket_strerror (errno));
-      arg = 0;
+      g_warning ("Error setting socket nonblocking: %s", error->message);
+      g_clear_error (&error);
     }
-
-  arg = arg | O_NONBLOCK;
-
-  if (fcntl (fd, F_SETFL, arg) < 0)
-      g_warning ("Error setting socket status flags: %s", socket_strerror (errno));
 #else
   arg = TRUE;
 
diff --git a/glib/glib-unix.c b/glib/glib-unix.c
index cf4748b..5a0f7f7 100644
--- a/glib/glib-unix.c
+++ b/glib/glib-unix.c
@@ -136,6 +136,56 @@ g_unix_pipe_flags (int     *fds,
 }
 
 /**
+ * g_unix_set_fd_nonblocking:
+ * @fd: A file descriptor
+ * @nonblock: If %TRUE, set the descriptor to be non-blocking
+ * @error: a #GError
+ *
+ * Control the non-blocking state of the given file descriptor,
+ * according to @nonblock.  On most systems this uses %O_NONBLOCK, but
+ * on some older ones may use %O_NDELAY.
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+g_unix_set_fd_nonblocking (gint       fd, 
+			   gboolean   nonblock,
+			   GError   **error)
+{
+#ifdef F_GETFL
+  glong fcntl_flags;
+  fcntl_flags = fcntl (fd, F_GETFL);
+
+  if (fcntl_flags == -1)
+    return g_unix_set_error_from_errno (error);
+
+  if (nonblock)
+    {
+#ifdef O_NONBLOCK
+      fcntl_flags |= O_NONBLOCK;
+#else
+      fcntl_flags |= O_NDELAY;
+#endif
+    }
+  else
+    {
+#ifdef O_NONBLOCK
+      fcntl_flags &= ~O_NONBLOCK;
+#else
+      fcntl_flags &= ~O_NDELAY;
+#endif
+    }
+
+  if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
+    return g_unix_set_error_from_errno (error);
+  return TRUE;
+#else
+  return g_unix_set_error_from_errno_saved (error, EINVAL);
+#endif
+}
+
+
+/**
  * g_unix_signal_source_new:
  * @signum: A signal number
  *
diff --git a/glib/glib-unix.h b/glib/glib-unix.h
index 55aaf25..de38c54 100644
--- a/glib/glib-unix.h
+++ b/glib/glib-unix.h
@@ -61,6 +61,10 @@ gboolean g_unix_pipe_flags (int      *fds,
 			    int       flags,
 			    GError  **error);
 
+gboolean g_unix_set_fd_nonblocking (gint       fd,
+				    gboolean   nonblock,
+				    GError   **error);
+
 GSource *g_unix_signal_source_new     (int signum);
 
 guint    g_unix_signal_add_watch_full (int            signum,
diff --git a/glib/glib.symbols b/glib/glib.symbols
index bc1c323..12b7430 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1983,6 +1983,7 @@ g_hostname_to_unicode
 #ifdef G_OS_UNIX
 g_unix_pipe_flags
 g_unix_error_quark
+g_unix_set_fd_nonblocking
 g_unix_signal_source_new
 g_unix_signal_add_watch_full
 #endif
diff --git a/glib/gmain.c b/glib/gmain.c
index f31405a..efcdcc3 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -4638,7 +4638,7 @@ init_unix_signal_wakeup_state_unlocked (void)
 
   if (!g_unix_pipe_flags (unix_signal_wake_up_pipe, FD_CLOEXEC, &error))
     g_error ("Cannot create UNIX signal wake up pipe: %s\n", error->message);
-  fcntl (unix_signal_wake_up_pipe[1], F_SETFL, O_NONBLOCK | fcntl (unix_signal_wake_up_pipe[1], F_GETFL));
+  g_unix_set_fd_nonblocking (unix_signal_wake_up_pipe[1], TRUE, NULL);
 
   /* We create a helper thread that polls on the wakeup pipe indefinitely */
   if (g_thread_create (unix_signal_helper_thread, NULL, FALSE, &error) == NULL)



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