static void soup_input_stream_prepare_for_io (GInputStream *stream, GCancellable *cancellable, guchar *buffer, gsize count) { SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); int cancel_fd; priv->cancellable = cancellable; cancel_fd = g_cancellable_get_fd (cancellable); if (cancel_fd != -1) { GIOChannel *chan = g_io_channel_unix_new (cancel_fd); priv->cancel_watch = soup_add_io_watch (priv->async_context, chan, G_IO_IN | G_IO_ERR | G_IO_HUP, soup_input_stream_cancelled, stream); g_io_channel_unref (chan); } priv->caller_buffer = buffer; priv->caller_bufsize = count; priv->caller_nread = 0; if (priv->got_headers) soup_session_unpause_message (priv->session, priv->msg); }
static void soup_output_stream_prepare_for_io (GOutputStream *stream, GCancellable *cancellable) { SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream); int cancel_fd; /* Move the buffer to the SoupMessage */ soup_message_body_append (priv->msg->request_body, SOUP_MEMORY_TAKE, priv->ba->data, priv->ba->len); g_byte_array_free (priv->ba, FALSE); priv->ba = NULL; /* Set up cancellation */ priv->cancellable = cancellable; cancel_fd = g_cancellable_get_fd (cancellable); if (cancel_fd != -1) { GIOChannel *chan = g_io_channel_unix_new (cancel_fd); priv->cancel_watch = soup_add_io_watch (priv->async_context, chan, G_IO_IN | G_IO_ERR | G_IO_HUP, soup_output_stream_cancelled, stream); g_io_channel_unref (chan); } /* Add an extra ref since soup_session_queue_message steals one */ g_object_ref (priv->msg); soup_session_queue_message (priv->session, priv->msg, NULL, NULL); }
/** * g_cancellable_make_pollfd: * @cancellable: a #GCancellable or %NULL * @pollfd: a pointer to a #GPollFD * * Creates a #GPollFD corresponding to @cancellable; this can be passed * to g_poll() and used to poll for cancellation. This is useful both * for unix systems without a native poll and for portability to * windows. * * When this function returns %TRUE, you should use * g_cancellable_release_fd() to free up resources allocated for the * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd(). * * 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 **/ gboolean g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd) { g_return_val_if_fail (pollfd != NULL, FALSE); if (cancellable == NULL) return FALSE; g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE); { #ifdef G_OS_WIN32 GCancellablePrivate *priv; priv = cancellable->priv; G_LOCK(cancellable); if (priv->event == NULL) { /* A manual reset anonymous event, starting unset */ priv->event = CreateEvent (NULL, TRUE, FALSE, NULL); if (priv->event == NULL) { G_UNLOCK(cancellable); return FALSE; } if (priv->cancelled) SetEvent(priv->event); } priv->fd_refcount++; G_UNLOCK(cancellable); pollfd->fd = (gintptr)priv->event; #else /* !G_OS_WIN32 */ int fd = g_cancellable_get_fd (cancellable); if (fd == -1) return FALSE; pollfd->fd = fd; #endif /* G_OS_WIN32 */ } pollfd->events = G_IO_IN; pollfd->revents = 0; return TRUE; }
static gssize g_unix_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { GUnixOutputStream *unix_stream; gssize res; struct pollfd poll_fds[2]; int poll_ret; int cancel_fd; unix_stream = G_UNIX_OUTPUT_STREAM (stream); cancel_fd = g_cancellable_get_fd (cancellable); if (cancel_fd != -1) { do { poll_fds[0].events = POLLOUT; poll_fds[0].fd = unix_stream->priv->fd; poll_fds[1].events = POLLIN; poll_fds[1].fd = cancel_fd; poll_ret = poll (poll_fds, 2, -1); } while (poll_ret == -1 && errno == EINTR); if (poll_ret == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to unix: %s"), g_strerror (errsv)); return -1; } } while (1) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; res = write (unix_stream->priv->fd, buffer, count); if (res == -1) { int errsv = errno; if (errsv == EINTR) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to unix: %s"), g_strerror (errsv)); } break; } return res; }