Пример #1
0
static gssize
g_unix_output_stream_write (GOutputStream  *stream,
                            const void     *buffer,
                            gsize           count,
                            GCancellable   *cancellable,
                            GError        **error)
{
    GUnixOutputStream *unix_stream;
    gssize res;
    GPollFD poll_fds[2];
    int poll_ret;

    unix_stream = G_UNIX_OUTPUT_STREAM (stream);

    if (g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
    {
        poll_fds[0].fd = unix_stream->priv->fd;
        poll_fds[0].events = G_IO_OUT;
        do
            poll_ret = g_poll (poll_fds, 2, -1);
        while (poll_ret == -1 && errno == EINTR);
        g_cancellable_release_fd (cancellable);

        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;
}
Пример #2
0
static void
gst_udpsrc_create_cancellable (GstUDPSrc * src)
{
  GPollFD pollfd;

  src->cancellable = g_cancellable_new ();
  src->made_cancel_fd = g_cancellable_make_pollfd (src->cancellable, &pollfd);
}
Пример #3
0
gboolean
wing_overlap_wait_result (HANDLE           hfile,
                          OVERLAPPED      *overlap,
                          DWORD           *transferred,
                          GCancellable    *cancellable)
{
  GPollFD pollfd[2];
  gboolean result = FALSE;
  gint num, npoll;

#if GLIB_SIZEOF_VOID_P == 8
  pollfd[0].fd = (gint64)overlap->hEvent;
#else
  pollfd[0].fd = (gint)overlap->hEvent;
#endif
  pollfd[0].events = G_IO_IN;
  num = 1;

  if (g_cancellable_make_pollfd (cancellable, &pollfd[1]))
    num++;

loop:
  npoll = g_poll (pollfd, num, -1);
  if (npoll <= 0)
    /* error out, should never happen */
    goto end;

  if (g_cancellable_is_cancelled (cancellable))
    {
      /* CancelIO only cancels pending operations issued by the
       * current thread and since we're doing only sync operations,
       * this is safe.... */
      /* CancelIoEx is only Vista+. Since we have only one overlap
       * operaton on this thread, we can just use: */
      result = CancelIo (hfile);
      g_warn_if_fail (result);
    }

  result = GetOverlappedResult (overlap->hEvent, overlap, transferred, FALSE);
  if (result == FALSE &&
      GetLastError () == ERROR_IO_INCOMPLETE &&
      !g_cancellable_is_cancelled (cancellable))
    goto loop;

end:
  if (num > 1)
    g_cancellable_release_fd (cancellable);

  return result;
}
Пример #4
0
/**
 * g_cancellable_get_fd:
 * @cancellable: a #GCancellable.
 * 
 * Gets the file descriptor for a cancellable job. This can be used to
 * implement cancellable operations on Unix systems. The returned fd will
 * turn readable when @cancellable is cancelled.
 *
 * 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().
 * 
 * After a successful return from this function, you should use 
 * g_cancellable_release_fd() to free up resources allocated for 
 * the returned file descriptor.
 *
 * See also g_cancellable_make_pollfd().
 *
 * Returns: A valid file descriptor. %-1 if the file descriptor 
 * is not supported, or on errors. 
 **/
int
g_cancellable_get_fd (GCancellable *cancellable)
{
  GPollFD pollfd;

  if (cancellable == NULL)
	  return -1;

#ifdef G_OS_WIN32
  pollfd.fd = -1;
#else
  g_cancellable_make_pollfd (cancellable, &pollfd);
#endif

  return pollfd.fd;
}
Пример #5
0
/*
 * g_socket_condition_timed_wait:
 *
 * Provides g_socket_condition_timed_wait function for older 
 * glib versions. It's a simplified version of the glib one
 * that should work with all glib version from glib-2.22.
 */
gboolean g_socket_condition_timed_wait(GSocket *socket,GIOCondition condition,gint64 timeout,GCancellable *cancellable,GError **error)
{
	gint64 start_time;
	GPollFD poll_fd[2];
	gint result;
	gint num;

	g_return_val_if_fail(G_IS_SOCKET(socket),FALSE);

	if(g_cancellable_set_error_if_cancelled(cancellable,error))
		return FALSE;

	if(timeout != -1)
		timeout /= 1000;

	start_time = g_get_monotonic_time();

	poll_fd[0].fd = g_socket_get_fd(socket);
	poll_fd[0].events = condition;
	num = 1;

	if(g_cancellable_make_pollfd(cancellable,&poll_fd[1]))
		num++;

	while(TRUE){
		result = g_poll(poll_fd,num,timeout);
		if(result != -1 || errno != EINTR)
			break;

		if(timeout != -1){
			timeout -= (g_get_monotonic_time () - start_time) * 1000;
			if(timeout < 0)
				timeout = 0;
		}
	}
    
	if(num > 1)
		g_cancellable_release_fd(cancellable);

	if(result == 0){
		g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_TIMED_OUT,
								"Socket I/O timed out");
		return FALSE;
	}

	return !g_cancellable_set_error_if_cancelled(cancellable,error);
}
Пример #6
0
static gboolean
byzanz_queue_input_stream_wait (ByzanzQueueInputStream *stream,
			        GCancellable *		cancellable,
				GError **		error)
{
  GPollFD fd;
  guint n_fds;
  
  /* FIXME: Use a file monitor here */

  /* Do the same thing that the UNIX tail program does: sleep a second */
  n_fds = 0;
  if (cancellable)
    {
      g_cancellable_make_pollfd (cancellable, &fd);
      n_fds++;
    }

  g_poll (&fd, n_fds, 1000);

  return !g_cancellable_set_error_if_cancelled (cancellable, error);
}
Пример #7
0
static gssize
g_unix_input_stream_read (GInputStream  *stream,
			  void          *buffer,
			  gsize          count,
			  GCancellable  *cancellable,
			  GError       **error)
{
  GUnixInputStream *unix_stream;
  gssize res = -1;
  GPollFD poll_fds[2];
  int nfds;
  int poll_ret;

  unix_stream = G_UNIX_INPUT_STREAM (stream);

  poll_fds[0].fd = unix_stream->priv->fd;
  poll_fds[0].events = G_IO_IN;
  if (unix_stream->priv->is_pipe_or_socket &&
      g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
    nfds = 2;
  else
    nfds = 1;

  while (1)
    {
      poll_fds[0].revents = poll_fds[1].revents = 0;
      do
	poll_ret = g_poll (poll_fds, nfds, -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 reading from file descriptor: %s"),
		       g_strerror (errsv));
	  break;
	}

      if (g_cancellable_set_error_if_cancelled (cancellable, error))
	break;

      if (!poll_fds[0].revents)
	continue;

      res = read (unix_stream->priv->fd, buffer, count);
      if (res == -1)
	{
          int errsv = errno;

	  if (errsv == EINTR || errsv == EAGAIN)
	    continue;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error reading from file descriptor: %s"),
		       g_strerror (errsv));
	}

      break;
    }

  if (nfds == 2)
    g_cancellable_release_fd (cancellable);
  return res;
}
Пример #8
0
static gboolean
claim_op (GTlsConnectionBase    *tls,
	  GTlsConnectionBaseOp   op,
	  gboolean               blocking,
	  GCancellable          *cancellable,
	  GError               **error)
{
 try_again:
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  g_mutex_lock (&tls->op_mutex);

  if (((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE ||
        op == G_TLS_CONNECTION_BASE_OP_READ) &&
       (tls->read_closing || tls->read_closed)) ||
      ((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE ||
        op == G_TLS_CONNECTION_BASE_OP_WRITE) &&
       (tls->write_closing || tls->write_closed)))
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
			   _("Connection is closed"));
      g_mutex_unlock (&tls->op_mutex);
      return FALSE;
    }

  if (tls->handshake_error &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE)
    {
      if (error)
	*error = g_error_copy (tls->handshake_error);
      g_mutex_unlock (&tls->op_mutex);
      return FALSE;
    }

  if (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE)
    {
      if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
          op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
          op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE &&
          tls->need_handshake && !tls->handshaking)
	{
	  tls->handshaking = TRUE;
	  if (!do_implicit_handshake (tls, blocking, cancellable, error))
	    {
	      g_cancellable_reset (tls->waiting_for_op);
	      g_mutex_unlock (&tls->op_mutex);
	      return FALSE;
	    }
	}

      if (tls->need_finish_handshake &&
	  tls->implicit_handshake)
	{
	  GError *my_error = NULL;
	  gboolean success;

	  tls->need_finish_handshake = FALSE;

	  g_mutex_unlock (&tls->op_mutex);
	  success = finish_handshake (tls, tls->implicit_handshake, &my_error);
	  g_clear_object (&tls->implicit_handshake);
	  g_mutex_lock (&tls->op_mutex);

	  if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
	      op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
	      op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE &&
	      (!success || g_cancellable_set_error_if_cancelled (cancellable, &my_error)))
	    {
	      g_propagate_error (error, my_error);
	      g_mutex_unlock (&tls->op_mutex);
	      return FALSE;
	    }

	  g_clear_error (&my_error);
	}
    }

  if ((op != G_TLS_CONNECTION_BASE_OP_WRITE && tls->reading) ||
      (op != G_TLS_CONNECTION_BASE_OP_READ && tls->writing) ||
      (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE && tls->handshaking))
    {
      GPollFD fds[2];
      int nfds;

      g_cancellable_reset (tls->waiting_for_op);

      g_mutex_unlock (&tls->op_mutex);

      if (!blocking)
	{
	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
			       _("Operation would block"));
	  return FALSE;
	}

      g_cancellable_make_pollfd (tls->waiting_for_op, &fds[0]);
      if (g_cancellable_make_pollfd (cancellable, &fds[1]))
	nfds = 2;
      else
	nfds = 1;

      g_poll (fds, nfds, -1);

      if (nfds > 1)
        g_cancellable_release_fd (cancellable);

      goto try_again;
    }

  if (op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE)
    tls->handshaking = TRUE;
  if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH ||
      op == G_TLS_CONNECTION_BASE_OP_CLOSE_READ)
    tls->read_closing = TRUE;
  if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH ||
      op == G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE)
    tls->write_closing = TRUE;

  if (op != G_TLS_CONNECTION_BASE_OP_WRITE)
    tls->reading = TRUE;
  if (op != G_TLS_CONNECTION_BASE_OP_READ)
    tls->writing = TRUE;

  g_mutex_unlock (&tls->op_mutex);
  return TRUE;
}
static gboolean
gst_net_client_internal_clock_start (GstNetClientInternalClock * self)
{
  GSocketAddress *servaddr;
  GSocketAddress *myaddr;
  GSocketAddress *anyaddr;
  GInetAddress *inetaddr;
  GSocket *socket;
  GError *error = NULL;
  GSocketFamily family;
  GPollFD dummy_pollfd;
  GResolver *resolver = NULL;
  GError *err = NULL;

  g_return_val_if_fail (self->address != NULL, FALSE);
  g_return_val_if_fail (self->servaddr == NULL, FALSE);

  /* create target address */
  inetaddr = g_inet_address_new_from_string (self->address);
  if (inetaddr == NULL) {
    GList *results;

    resolver = g_resolver_get_default ();

    results = g_resolver_lookup_by_name (resolver, self->address, NULL, &err);
    if (!results)
      goto failed_to_resolve;

    inetaddr = G_INET_ADDRESS (g_object_ref (results->data));
    g_resolver_free_addresses (results);
    g_object_unref (resolver);
  }

  family = g_inet_address_get_family (inetaddr);

  servaddr = g_inet_socket_address_new (inetaddr, self->port);
  g_object_unref (inetaddr);

  g_assert (servaddr != NULL);

  GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address,
      self->port);

  socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM,
      G_SOCKET_PROTOCOL_UDP, &error);

  if (socket == NULL)
    goto no_socket;

  GST_DEBUG_OBJECT (self, "binding socket");
  inetaddr = g_inet_address_new_any (family);
  anyaddr = g_inet_socket_address_new (inetaddr, 0);
  g_socket_bind (socket, anyaddr, TRUE, &error);
  g_object_unref (anyaddr);
  g_object_unref (inetaddr);

  if (error != NULL)
    goto bind_error;

  /* check address we're bound to, mostly for debugging purposes */
  myaddr = g_socket_get_local_address (socket, &error);

  if (myaddr == NULL)
    goto getsockname_error;

  GST_DEBUG_OBJECT (self, "socket opened on UDP port %d",
      g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr)));

  g_object_unref (myaddr);

  self->cancel = g_cancellable_new ();
  self->made_cancel_fd =
      g_cancellable_make_pollfd (self->cancel, &dummy_pollfd);

  self->socket = socket;
  self->servaddr = G_SOCKET_ADDRESS (servaddr);

  self->thread = g_thread_try_new ("GstNetClientInternalClock",
      gst_net_client_internal_clock_thread, self, &error);

  if (error != NULL)
    goto no_thread;

  return TRUE;

  /* ERRORS */
no_socket:
  {
    GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message);
    g_error_free (error);
    return FALSE;
  }
bind_error:
  {
    GST_ERROR_OBJECT (self, "bind failed: %s", error->message);
    g_error_free (error);
    g_object_unref (socket);
    return FALSE;
  }
getsockname_error:
  {
    GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message);
    g_error_free (error);
    g_object_unref (socket);
    return FALSE;
  }
failed_to_resolve:
  {
    GST_ERROR_OBJECT (self, "resolving '%s' failed: %s",
        self->address, err->message);
    g_clear_error (&err);
    g_object_unref (resolver);
    return FALSE;
  }
no_thread:
  {
    GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
    g_object_unref (self->servaddr);
    self->servaddr = NULL;
    g_object_unref (self->socket);
    self->socket = NULL;
    g_error_free (error);
    return FALSE;
  }
}
Пример #10
0
static gboolean
g_unix_output_stream_writev (GOutputStream        *stream,
			     const GOutputVector  *vectors,
			     gsize                 n_vectors,
			     gsize                *bytes_written,
			     GCancellable         *cancellable,
			     GError              **error)
{
  GUnixOutputStream *unix_stream;
  gssize res = -1;
  GPollFD poll_fds[2];
  int nfds = 0;
  int poll_ret;
  struct iovec *iov;

  if (bytes_written)
    *bytes_written = 0;

  /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
   * We handle this like a short write in this case
   */
  if (n_vectors > G_MAXINT)
    n_vectors = G_MAXINT;

  unix_stream = G_UNIX_OUTPUT_STREAM (stream);

  if (G_OUTPUT_VECTOR_IS_IOVEC)
    {
      /* ABI is compatible */
      iov = (struct iovec *) vectors;
    }
  else
    {
      gsize i;

      /* ABI is incompatible */
      iov = g_newa (struct iovec, n_vectors);
      for (i = 0; i < n_vectors; i++)
        {
          iov[i].iov_base = (void *)vectors[i].buffer;
          iov[i].iov_len = vectors[i].size;
        }
    }

  poll_fds[0].fd = unix_stream->priv->fd;
  poll_fds[0].events = G_IO_OUT;
  nfds++;

  if (unix_stream->priv->is_pipe_or_socket &&
      g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
    nfds++;

  while (1)
    {
      int errsv;

      poll_fds[0].revents = poll_fds[1].revents = 0;
      do
        {
          poll_ret = g_poll (poll_fds, nfds, -1);
          errsv = errno;
        }
      while (poll_ret == -1 && errsv == EINTR);

      if (poll_ret == -1)
	{
	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error writing to file descriptor: %s"),
		       g_strerror (errsv));
	  break;
	}

      if (g_cancellable_set_error_if_cancelled (cancellable, error))
	break;

      if (!poll_fds[0].revents)
	continue;

      res = writev (unix_stream->priv->fd, iov, n_vectors);
      errsv = errno;
      if (res == -1)
	{
	  if (errsv == EINTR || errsv == EAGAIN)
	    continue;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error writing to file descriptor: %s"),
		       g_strerror (errsv));
	}

      if (bytes_written)
        *bytes_written = res;

      break;
    }

  if (nfds == 2)
    g_cancellable_release_fd (cancellable);
  return res != -1;
}