[glib] Bug 591714 – Figure out failure handling for g_cancellable_make_pollfd()



commit bb8e4f06ab1a0ada2c8835284ec5f853378694e2
Author: Benjamin Otte <otte gnome org>
Date:   Thu Aug 13 20:19:15 2009 +0200

    Bug 591714 â?? Figure out failure handling for g_cancellable_make_pollfd()
    
    Make g_cancellable_make_pollfd() return a gboolean that indicates its error
    status. Update the code that calls this function accordingly.

 gio/gcancellable.c      |   38 +++++++++++++++++++++++++-------------
 gio/gcancellable.h      |    2 +-
 gio/gsocket.c           |   19 ++++++-------------
 gio/gunixinputstream.c  |    3 +--
 gio/gunixoutputstream.c |    3 +--
 5 files changed, 34 insertions(+), 31 deletions(-)
---
diff --git a/gio/gcancellable.c b/gio/gcancellable.c
index 88490b0..ada764a 100644
--- a/gio/gcancellable.c
+++ b/gio/gcancellable.c
@@ -55,7 +55,6 @@ struct _GCancellablePrivate
   GObject parent_instance;
 
   guint cancelled : 1;
-  guint allocated_pipe : 1;
   guint cancelled_running : 1;
   guint cancelled_running_waiting : 1;
   int cancel_pipe[2];
@@ -224,8 +223,6 @@ g_cancellable_open_pipe (GCancellable *cancellable)
       set_fd_close_exec (priv->cancel_pipe[0]);
       set_fd_close_exec (priv->cancel_pipe[1]);
     }
-  else
-    g_warning ("Failed to create pipe for GCancellable. Out of file descriptors?");
 }
 #endif
 
@@ -440,11 +437,8 @@ g_cancellable_get_fd (GCancellable *cancellable)
   return -1;
 #else
   G_LOCK(cancellable);
-  if (!priv->allocated_pipe)
-    {
-      priv->allocated_pipe = TRUE;
-      g_cancellable_open_pipe (cancellable);
-    }
+  if (priv->cancel_pipe[0] == -1)
+    g_cancellable_open_pipe (cancellable);
 
   fd = priv->cancel_pipe[0];
   G_UNLOCK(cancellable);
@@ -455,7 +449,7 @@ g_cancellable_get_fd (GCancellable *cancellable)
 
 /**
  * g_cancellable_make_pollfd:
- * @cancellable: a #GCancellable.
+ * @cancellable: a #GCancellable or %NULL
  * @pollfd: a pointer to a #GPollFD
  * 
  * Creates a #GPollFD corresponding to @cancellable; this can be passed
@@ -463,18 +457,31 @@ g_cancellable_get_fd (GCancellable *cancellable)
  * for unix systems without a native poll and for portability to
  * windows.
  *
+ * If this function returns %FALSE, either no @cancellable was given or
+ * resource limits prevent this function from allocating the necessary 
+ * structures for polling. (On Linux, you will likely have reached 
+ * the maximum number of file descriptors.) The suggested way to handle
+ * these cases is to ignore the @cancellable.
+ *
  * You are not supposed to read from the fd yourself, just check for
  * readable status. Reading to unset the readable status is done
  * with g_cancellable_reset().
+ *
+ * @Returns: %TRUE if @pollfd was successfully initialized, %FALSE on 
+ *           failure to prepare the cancellable.
  * 
+ * @Since: 2.22
  **/
-void
+gboolean
 g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
 {
   GCancellablePrivate *priv;
+  int fd;
 
-  g_return_if_fail (G_IS_CANCELLABLE (cancellable));
-  g_return_if_fail (pollfd != NULL);
+  g_return_val_if_fail (pollfd != NULL, FALSE);
+  if (cancellable == NULL)
+    return FALSE;
+  g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);
 
   priv = cancellable->priv;
 
@@ -483,10 +490,15 @@ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
     {
       /* A manual reset anonymous event, starting unset */
       priv->event = CreateEvent (NULL, TRUE, FALSE, NULL);
+      if (priv->event == NULL)
+        return FALSE;
     }
   pollfd->fd = (gintptr)priv->event;
 #else /* !G_OS_WIN32 */
-  pollfd->fd = g_cancellable_get_fd (cancellable);
+  fd = g_cancellable_get_fd (cancellable);
+  if (fd == -1)
+    return -1;
+  pollfd->fd = fd;
 #endif /* G_OS_WIN32 */
   pollfd->events = G_IO_IN;
   pollfd->revents = 0;
diff --git a/gio/gcancellable.h b/gio/gcancellable.h
index 714899d..9d318c2 100644
--- a/gio/gcancellable.h
+++ b/gio/gcancellable.h
@@ -79,7 +79,7 @@ gboolean      g_cancellable_set_error_if_cancelled (GCancellable  *cancellable,
 						    GError       **error);
 
 int           g_cancellable_get_fd                 (GCancellable  *cancellable);
-void          g_cancellable_make_pollfd            (GCancellable  *cancellable,
+gboolean      g_cancellable_make_pollfd            (GCancellable  *cancellable,
 						    GPollFD       *pollfd);
 
 GCancellable *g_cancellable_get_current            (void);
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 3f92c75..923212b 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -2291,11 +2291,10 @@ winsock_source_new (GSocket      *socket,
   winsock_source->condition = condition;
   add_condition_watch (socket, &winsock_source->condition);
 
-  if (cancellable)
+  if (g_cancellable_make_pollfd (cancellable,
+                                 &winsock_source->cancel_pollfd))
     {
       winsock_source->cancellable = g_object_ref (cancellable);
-      g_cancellable_make_pollfd (cancellable,
-				 &winsock_source->cancel_pollfd);
       g_source_add_poll (source, &winsock_source->cancel_pollfd);
     }
 
@@ -2446,11 +2445,8 @@ g_socket_condition_wait (GSocket       *socket,
     num_events = 0;
     events[num_events++] = socket->priv->event;
 
-    if (cancellable)
-      {
-	g_cancellable_make_pollfd (cancellable, &cancel_fd);
-	events[num_events++] = (WSAEVENT)cancel_fd.fd;
-      }
+    if (g_cancellable_make_pollfd (cancellable, &cancel_fd))
+      events[num_events++] = (WSAEVENT)cancel_fd.fd;
 
     current_condition = update_condition (socket);
     while ((condition & current_condition) == 0)
@@ -2487,11 +2483,8 @@ g_socket_condition_wait (GSocket       *socket,
     poll_fd[0].events = condition;
     num = 1;
 
-    if (cancellable)
-      {
-	g_cancellable_make_pollfd (cancellable, &poll_fd[1]);
-	num++;
-      }
+    if (g_cancellable_make_pollfd (cancellable, &poll_fd[1]))
+      num++;
 
     do
       result = g_poll (poll_fd, num, -1);
diff --git a/gio/gunixinputstream.c b/gio/gunixinputstream.c
index 2813aad..a6038b8 100644
--- a/gio/gunixinputstream.c
+++ b/gio/gunixinputstream.c
@@ -340,11 +340,10 @@ g_unix_input_stream_read (GInputStream  *stream,
 
   unix_stream = G_UNIX_INPUT_STREAM (stream);
 
-  if (cancellable)
+  if (g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
     {
       poll_fds[0].fd = unix_stream->priv->fd;
       poll_fds[0].events = G_IO_IN;
-      g_cancellable_make_pollfd (cancellable, &poll_fds[1]);
       do
 	poll_ret = g_poll (poll_fds, 2, -1);
       while (poll_ret == -1 && errno == EINTR);
diff --git a/gio/gunixoutputstream.c b/gio/gunixoutputstream.c
index 147561b..1680cd3 100644
--- a/gio/gunixoutputstream.c
+++ b/gio/gunixoutputstream.c
@@ -326,11 +326,10 @@ g_unix_output_stream_write (GOutputStream  *stream,
 
   unix_stream = G_UNIX_OUTPUT_STREAM (stream);
 
-  if (cancellable)
+  if (g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
     {
       poll_fds[0].fd = unix_stream->priv->fd;
       poll_fds[0].events = G_IO_OUT;
-      g_cancellable_make_pollfd (cancellable, &poll_fds[1]);
       do
 	poll_ret = g_poll (poll_fds, 2, -1);
       while (poll_ret == -1 && errno == EINTR);



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