Beispiel #1
0
/** 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;
}
Beispiel #2
0
/** 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;
}
Beispiel #3
0
/** 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;
}
Beispiel #4
0
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;
}