From: Benjamin Otte Date: Thu, 13 Aug 2009 18:19:15 +0000 (+0200) Subject: Bug 591714 – Figure out failure handling for g_cancellable_make_pollfd() X-Git-Tag: 2.21.5~19 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bb8e4f06ab1a0ada2c8835284ec5f853378694e2;p=platform%2Fupstream%2Fglib.git 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. --- diff --git a/gio/gcancellable.c b/gio/gcancellable.c index 88490b041..ada764a1a 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 714899d68..9d318c270 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 3f92c7573..923212ba6 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 2813aad2b..a6038b8c0 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 147561b46..1680cd359 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);