/** Dispatch events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * * Dispatch all incoming events for objects assigned to the given * event queue. On failure -1 is returned and errno set appropriately. * * This function blocks if there are no events to dispatch. If calling from * the main thread, it will block reading data from the display fd. For other * threads this will block until the main thread queues events on the queue * passed as argument. * * \memberof wl_display */ WL_EXPORT int wl_display_dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) { struct pollfd pfd[2]; int ret; pthread_mutex_lock(&display->mutex); ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; if (ret > 0) { pthread_mutex_unlock(&display->mutex); return ret; } /* We ignore EPIPE here, so that we try to read events before * returning an error. When the compositor sends an error it * will close the socket, and if we bail out here we don't get * a chance to process the error. */ ret = wl_connection_flush(display->connection); if (ret < 0 && errno != EAGAIN && errno != EPIPE) { display_fatal_error(display, errno); goto err_unlock; } display->reader_count++; pthread_mutex_unlock(&display->mutex); pfd[0].fd = display->fd; pfd[0].events = POLLIN; do { ret = poll(pfd, 1, -1); } while (ret == -1 && errno == EINTR); if (ret == -1) { wl_display_cancel_read(display); return -1; } pthread_mutex_lock(&display->mutex); if (read_events(display) == -1) goto err_unlock; ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; pthread_mutex_unlock(&display->mutex); return ret; err_unlock: pthread_mutex_unlock(&display->mutex); return -1; }
/** Dispatch events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * * Dispatch all incoming events for objects assigned to the given * event queue. On failure -1 is returned and errno set appropriately. * * This function blocks if there are no events to dispatch. If calling from * the main thread, it will block reading data from the display fd. For other * threads this will block until the main thread queues events on the queue * passed as argument. * * \memberof wl_display */ WL_EXPORT int wl_display_dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) { struct pollfd pfd[2]; int ret; pthread_mutex_lock(&display->mutex); ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; if (ret > 0) { pthread_mutex_unlock(&display->mutex); return ret; } ret = wl_connection_flush(display->connection); if (ret < 0 && errno != EAGAIN) { display_fatal_error(display, errno); goto err_unlock; } display->reader_count++; pthread_mutex_unlock(&display->mutex); pfd[0].fd = display->fd; pfd[0].events = POLLIN; do { ret = poll(pfd, 1, -1); } while (ret == -1 && errno == EINTR); if (ret == -1) { wl_display_cancel_read(display); return -1; } pthread_mutex_lock(&display->mutex); if (read_events(display) == -1) goto err_unlock; ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; pthread_mutex_unlock(&display->mutex); return ret; err_unlock: pthread_mutex_unlock(&display->mutex); return -1; }
/** Dispatch pending events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * * Dispatch all incoming events for objects assigned to the given * event queue. On failure -1 is returned and errno set appropriately. * If there are no events queued, this function returns immediately. * * \memberof wl_display * \since 1.0.2 */ WL_EXPORT int wl_display_dispatch_queue_pending(struct wl_display *display, struct wl_event_queue *queue) { int ret; pthread_mutex_lock(&display->mutex); ret = dispatch_queue(display, queue); pthread_mutex_unlock(&display->mutex); return ret; }
static gboolean cockpit_ssh_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { CockpitSshSource *cs = (CockpitSshSource *)source; CockpitSshTransport *self = cs->transport; GIOCondition cond = cs->pfd.revents; const gchar *msg; gint rc; g_return_val_if_fail ((cond & G_IO_NVAL) == 0, FALSE); g_assert (self->data != NULL); if (self->drain_buffer) { self->drain_buffer = 0; drain_buffer (self); } if (cond & (G_IO_HUP | G_IO_ERR)) { if (self->sent_close || self->sent_eof) { self->received_eof = TRUE; self->received_close = TRUE; } } /* * HACK: Yes this is anohter poll() call. The async support in * libssh is quite hacky right now. * * https://red.libssh.org/issues/155 */ rc = ssh_event_dopoll (self->event, 0); switch (rc) { case SSH_OK: case SSH_AGAIN: break; case SSH_ERROR: msg = ssh_get_error (self->data->session); /* * HACK: There doesn't seem to be a way to get at the original socket errno * here. So we have to screen scrape. * * https://red.libssh.org/issues/158 */ if (msg && (strstr (msg, "disconnected") || strstr (msg, "SSH_MSG_DISCONNECT") || strstr (msg, "Socket error: Success") || strstr (msg, "Socket error: Connection reset by peer"))) { g_debug ("%s: failed to process channel: %s", self->logname, msg); close_immediately (self, "terminated"); } else { g_message ("%s: failed to process channel: %s", self->logname, msg); close_immediately (self, "internal-error"); } return TRUE; default: g_critical ("%s: ssh_event_dopoll() returned %d", self->logname, rc); return FALSE; } if (cond & G_IO_ERR) { g_message ("%s: error reading from ssh", self->logname); close_immediately (self, "disconnected"); return TRUE; } if (self->drain_buffer) { self->drain_buffer = 0; drain_buffer (self); } if (cond & G_IO_OUT) { if (!dispatch_queue (self) && self->closing && !self->sent_eof) dispatch_eof (self); if (self->received_eof && self->sent_eof && !self->sent_close) dispatch_close (self); if (self->received_close && !self->sent_close) dispatch_close (self); } return TRUE; }