Bug 591714 – Figure out failure handling for g_cancellable_make_pollfd()
authorBenjamin Otte <otte@gnome.org>
Thu, 13 Aug 2009 18:19:15 +0000 (20:19 +0200)
committerBenjamin Otte <otte@gnome.org>
Wed, 19 Aug 2009 09:02:05 +0000 (11:02 +0200)
Make g_cancellable_make_pollfd() return a gboolean that indicates its error
status. Update the code that calls this function accordingly.

gio/gcancellable.c
gio/gcancellable.h
gio/gsocket.c
gio/gunixinputstream.c
gio/gunixoutputstream.c

index 88490b04110cf395bbb363e0be7a2fccd5d5f6e5..ada764a1a0b13fdfd018f756bdbb644c4852e00a 100644 (file)
@@ -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;
index 714899d68e065d99c41c45dce26919b13f6ca9f3..9d318c2708113d9a6fd252cf3ae102e8691cfaa8 100644 (file)
@@ -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);
index 3f92c7573e5dc936c99a2a51ac113827504d3739..923212ba678a2de6d9c3ed8b697176b10abd8bff 100644 (file)
@@ -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);
index 2813aad2b61323651aad68e33c5bc3eb27b487a4..a6038b8c0be296220eb95e0cf608678f11bee321 100644 (file)
@@ -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);
index 147561b46f8a87e6d0a252d8986da89b48060ec0..1680cd359ea9eec815e76e8e9d27c214390cd4f8 100644 (file)
@@ -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);