Ejemplo n.º 1
0
static void
shutdown_fd_locked (FsMsnConnection *self, FsMsnPollFD *pollfd, gboolean equal)
{
  gint i;
  guint closed = 0;

  for (i = 0; i < self->pollfds->len; i++)
  {
    FsMsnPollFD *p = g_ptr_array_index(self->pollfds, i);
    if ((equal && p == pollfd) || (!equal && p != pollfd))
    {
      GST_DEBUG ("Shutting down p %p (fd %d)", p, p->pollfd.fd);

      if (!gst_poll_fd_has_closed (self->poll, &p->pollfd))
        close (p->pollfd.fd);
      if (!gst_poll_remove_fd (self->poll, &p->pollfd))
        GST_WARNING ("Could not remove pollfd %p", p);
      g_ptr_array_remove_index_fast (self->pollfds, i);
      g_slice_free (FsMsnPollFD, p);
      closed++;
      i--;
    }
  }

  if (closed)
    gst_poll_restart (self->poll);
  else
    GST_WARNING ("Could find pollfd to remove");
}
Ejemplo n.º 2
0
static void
gst_fd_src_update_fd (GstFdSrc * src, guint64 size)
{
  struct stat stat_results;

  GST_DEBUG_OBJECT (src, "fdset %p, old_fd %d, new_fd %d", src->fdset, src->fd,
      src->new_fd);

  /* we need to always update the fdset since it may not have existed when
   * gst_fd_src_update_fd () was called earlier */
  if (src->fdset != NULL) {
    GstPollFD fd = GST_POLL_FD_INIT;

    if (src->fd >= 0) {
      fd.fd = src->fd;
      /* this will log a harmless warning, if it was never added */
      gst_poll_remove_fd (src->fdset, &fd);
    }

    fd.fd = src->new_fd;
    gst_poll_add_fd (src->fdset, &fd);
    gst_poll_fd_ctl_read (src->fdset, &fd, TRUE);
  }


  if (src->fd != src->new_fd) {
    GST_INFO_OBJECT (src, "Updating to fd %d", src->new_fd);

    src->fd = src->new_fd;

    GST_INFO_OBJECT (src, "Setting size to fd %" G_GUINT64_FORMAT, size);
    src->size = size;

    g_free (src->uri);
    src->uri = g_strdup_printf ("fd://%d", src->fd);

    if (fstat (src->fd, &stat_results) < 0)
      goto not_seekable;

    if (!S_ISREG (stat_results.st_mode))
      goto not_seekable;

    /* Try a seek of 0 bytes offset to check for seekability */
    if (lseek (src->fd, 0, SEEK_CUR) < 0)
      goto not_seekable;

    GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd);
    src->seekable_fd = TRUE;

    gst_base_src_set_dynamic_size (GST_BASE_SRC (src), TRUE);
  }
  return;

not_seekable:
  {
    GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd);
    src->seekable_fd = FALSE;
    gst_base_src_set_dynamic_size (GST_BASE_SRC (src), FALSE);
  }
}
Ejemplo n.º 3
0
static gboolean
gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd)
{
  if (new_fd < 0)
    return FALSE;

  if (!gst_fd_sink_check_fd (fdsink, new_fd))
    goto invalid;

  /* assign the fd */
  GST_OBJECT_LOCK (fdsink);
  if (fdsink->fdset) {
    GstPollFD fd = GST_POLL_FD_INIT;

    fd.fd = fdsink->fd;
    gst_poll_remove_fd (fdsink->fdset, &fd);

    fd.fd = new_fd;
    gst_poll_add_fd (fdsink->fdset, &fd);
    gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
  }
  fdsink->fd = new_fd;
  g_free (fdsink->uri);
  fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);

  GST_OBJECT_UNLOCK (fdsink);

  return TRUE;

invalid:
  {
    return FALSE;
  }
}
Ejemplo n.º 4
0
static void
gst_net_time_provider_stop (GstNetTimeProvider * self)
{
  gst_poll_set_flushing (self->priv->fdset, TRUE);
  g_thread_join (self->thread);
  self->thread = NULL;

  if (self->priv->sock.fd != -1) {
    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
  }
}
Ejemplo n.º 5
0
static void
plugin_loader_cleanup_child (GstPluginLoader * l)
{
  if (!l->child_running || l->is_child)
    return;

  gst_poll_remove_fd (l->fdset, &l->fd_w);
  gst_poll_remove_fd (l->fdset, &l->fd_r);

  close (l->fd_w.fd);
  close (l->fd_r.fd);

#ifndef G_OS_WIN32
  GST_LOG ("waiting for child process to exit");
  waitpid (l->child_pid, NULL, 0);
#else
  g_warning ("FIXME: Implement child process shutdown for Win32");
#endif
  g_spawn_close_pid (l->child_pid);

  l->child_running = FALSE;
}
Ejemplo n.º 6
0
static void
gst_net_client_clock_stop (GstNetClientClock * self)
{
  gst_poll_set_flushing (self->priv->fdset, TRUE);
  g_thread_join (self->thread);
  self->thread = NULL;

  if (self->priv->sock.fd != -1) {
    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
  }
}
Ejemplo n.º 7
0
static void
gst_fd_src_update_fd (GstFdSrc * src)
{
  struct stat stat_results;

  /* we need to always update the fdset since it may not have existed when
   * gst_fd_src_update_fd() was called earlier */
  if (src->fdset != NULL) {
    GstPollFD fd = GST_POLL_FD_INIT;

    if (src->fd >= 0) {
      fd.fd = src->fd;
      gst_poll_remove_fd (src->fdset, &fd);
    }

    fd.fd = src->new_fd;
    gst_poll_add_fd (src->fdset, &fd);
    gst_poll_fd_ctl_read (src->fdset, &fd, TRUE);
  }

  if (src->fd != src->new_fd) {
    GST_INFO_OBJECT (src, "Updating to fd %d", src->new_fd);

    src->fd = src->new_fd;

    g_free (src->uri);
    src->uri = g_strdup_printf ("fd://%d", src->fd);

    if (fstat (src->fd, &stat_results) < 0)
      goto not_seekable;

    if (!S_ISREG (stat_results.st_mode))
      goto not_seekable;

    /* Try a seek of 0 bytes offset to check for seekability */
    if (lseek (src->fd, 0, SEEK_CUR) < 0)
      goto not_seekable;

    GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd);
    src->seekable_fd = TRUE;
  }
  return;

not_seekable:
  {
    GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd);
    src->seekable_fd = FALSE;
  }
}
Ejemplo n.º 8
0
static void
gst_shm_src_stop_reading (GstShmSrc * self)
{
  GST_DEBUG_OBJECT (self, "Stopping %p", self);

  if (self->pipe) {
    gst_shm_pipe_dec (self->pipe);
    self->pipe = NULL;
  }

  gst_poll_remove_fd (self->poll, &self->pollfd);
  gst_poll_fd_init (&self->pollfd);

  gst_poll_set_flushing (self->poll, TRUE);
}
Ejemplo n.º 9
0
static gboolean
gst_avdtp_src_stop (GstBaseSrc * bsrc)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);

  gst_poll_remove_fd (avdtpsrc->poll, &avdtpsrc->pfd);
  gst_poll_set_flushing (avdtpsrc->poll, TRUE);

  gst_avdtp_connection_release (&avdtpsrc->conn);

  if (avdtpsrc->dev_caps) {
    gst_caps_unref (avdtpsrc->dev_caps);
    avdtpsrc->dev_caps = NULL;
  }

  return TRUE;
}
Ejemplo n.º 10
0
/******************************************************
 * gst_v4l2_close():
 *   close the video device (v4l2object->video_fd)
 * return value: TRUE on success, FALSE on error
 ******************************************************/
gboolean
gst_v4l2_close (GstV4l2Object * v4l2object)
{
  GstPollFD pollfd = GST_POLL_FD_INIT;
  GST_DEBUG_OBJECT (v4l2object->element, "Trying to close %s",
      v4l2object->videodev);

  GST_V4L2_CHECK_OPEN (v4l2object);
  GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);

  /* close device */
  v4l2_close (v4l2object->video_fd);
  pollfd.fd = v4l2object->video_fd;
  gst_poll_remove_fd (v4l2object->poll, &pollfd);
  v4l2object->video_fd = -1;

  /* empty lists */
  gst_v4l2_empty_lists (v4l2object);

  return TRUE;
}
/* This function gets called by libcurl after the socket() call but before
 * the connect() call. */
static int
gst_curl_base_sink_transfer_socket_cb (void *clientp, curl_socket_t curlfd,
    curlsocktype socket_type)
{
  GstCurlBaseSink *sink;
  gboolean ret = TRUE;

  sink = (GstCurlBaseSink *) clientp;

  g_assert (sink);

  if (curlfd < 0) {
    /* signal an unrecoverable error to the library which will close the socket
       and return CURLE_COULDNT_CONNECT
     */
    GST_DEBUG_OBJECT (sink, "no curlfd");
    return 1;
  }

  GST_OBJECT_LOCK (sink);
  sink->socket_type = socket_type;

  if (sink->fd.fd != curlfd) {
    if (sink->fd.fd > 0 && sink->socket_type != CURLSOCKTYPE_ACCEPT) {
      ret &= gst_poll_remove_fd (sink->fdset, &sink->fd);
    }
    sink->fd.fd = curlfd;
    ret &= gst_poll_add_fd (sink->fdset, &sink->fd);
    ret &= gst_poll_fd_ctl_write (sink->fdset, &sink->fd, TRUE);
    ret &= gst_poll_fd_ctl_read (sink->fdset, &sink->fd, TRUE);
  }
  GST_DEBUG_OBJECT (sink, "fd: %d", sink->fd.fd);
  gst_curl_base_sink_setup_dscp_unlocked (sink);
  GST_OBJECT_UNLOCK (sink);

  /* success */
  return ret ? 0 : 1;
}
Ejemplo n.º 12
0
static gboolean
gst_kms_sink_stop (GstBaseSink * bsink)
{
  GstKMSSink *self;

  self = GST_KMS_SINK (bsink);

  gst_buffer_replace (&self->last_buffer, NULL);
  gst_caps_replace (&self->allowed_caps, NULL);
  gst_object_replace ((GstObject **) & self->pool, NULL);
  gst_object_replace ((GstObject **) & self->allocator, NULL);

  gst_poll_remove_fd (self->poll, &self->pollfd);
  gst_poll_restart (self->poll);
  gst_poll_fd_init (&self->pollfd);

  if (self->fd >= 0) {
    drmClose (self->fd);
    self->fd = -1;
  }

  return TRUE;
}
Ejemplo n.º 13
0
static gboolean
gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd, GError ** error)
{
  if (new_fd < 0) {
    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE,
        "File descriptor %d is not valid", new_fd);
    return FALSE;
  }

  if (!gst_fd_sink_check_fd (fdsink, new_fd, error))
    goto invalid;

  /* assign the fd */
  GST_OBJECT_LOCK (fdsink);
  if (fdsink->fdset) {
    GstPollFD fd = GST_POLL_FD_INIT;

    fd.fd = fdsink->fd;
    gst_poll_remove_fd (fdsink->fdset, &fd);

    fd.fd = new_fd;
    gst_poll_add_fd (fdsink->fdset, &fd);
    gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
  }
  fdsink->fd = new_fd;
  g_free (fdsink->uri);
  fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);

  GST_OBJECT_UNLOCK (fdsink);

  return TRUE;

invalid:
  {
    return FALSE;
  }
}
Ejemplo n.º 14
0
static gboolean
gst_net_time_provider_start (GstNetTimeProvider * self)
{
  gint ru;
  struct sockaddr_in my_addr;
  guint len;
  int port;
  gint ret;
  GError *error;

  if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    goto no_socket;

  self->priv->sock.fd = ret;

  ru = 1;
  ret =
      setsockopt (self->priv->sock.fd, SOL_SOCKET, SO_REUSEADDR, &ru,
      sizeof (ru));
  if (ret < 0)
    goto setsockopt_error;

  memset (&my_addr, 0, sizeof (my_addr));
  my_addr.sin_family = AF_INET; /* host byte order */
  my_addr.sin_port = htons ((gint16) self->port);       /* short, network byte order */
  my_addr.sin_addr.s_addr = INADDR_ANY;
  if (self->address)
    inet_aton (self->address, &my_addr.sin_addr);

  GST_DEBUG_OBJECT (self, "binding on port %d", self->port);
  ret =
      bind (self->priv->sock.fd, (struct sockaddr *) &my_addr,
      sizeof (my_addr));
  if (ret < 0)
    goto bind_error;

  len = sizeof (my_addr);
#ifdef G_OS_WIN32
  ret =
      getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr,
      (gint *) & len);
#else
  ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr, &len);
#endif
  if (ret < 0)
    goto getsockname_error;

  port = ntohs (my_addr.sin_port);
  GST_DEBUG_OBJECT (self, "bound, on port %d", port);

  if (port != self->port) {
    self->port = port;
    GST_DEBUG_OBJECT (self, "notifying %d", port);
    g_object_notify (G_OBJECT (self), "port");
  }

  gst_poll_add_fd (self->priv->fdset, &self->priv->sock);
  gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE);

  self->thread = g_thread_create (gst_net_time_provider_thread, self, TRUE,
      &error);
  if (!self->thread)
    goto no_thread;

  return TRUE;

  /* ERRORS */
no_socket:
  {
    GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    return FALSE;
  }
setsockopt_error:
  {
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    GST_ERROR_OBJECT (self, "setsockopt failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    return FALSE;
  }
bind_error:
  {
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    GST_ERROR_OBJECT (self, "bind failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    return FALSE;
  }
getsockname_error:
  {
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    return FALSE;
  }
no_thread:
  {
    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
    g_error_free (error);
    return FALSE;
  }
}
Ejemplo n.º 15
0
static gpointer
pollthread_func (gpointer data)
{
  GstShmSink *self = GST_SHM_SINK (data);
  GList *item;
  GstClockTime timeout = GST_CLOCK_TIME_NONE;
  int rv = 0;

  while (!self->stop) {

    do {
      rv = gst_poll_wait (self->poll, timeout);
    } while (rv < 0 && errno == EINTR);

    if (rv < 0) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ,
          ("Failed waiting on fd activity"),
          ("gst_poll_wait returned %d, errno: %d", rv, errno));
      return NULL;
    }

    timeout = GST_CLOCK_TIME_NONE;

    if (self->stop)
      return NULL;

    if (gst_poll_fd_has_closed (self->poll, &self->serverpollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed read from shmsink"),
          ("Control socket has closed"));
      return NULL;
    }

    if (gst_poll_fd_has_error (self->poll, &self->serverpollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"),
          ("Control socket has error"));
      return NULL;
    }

    if (gst_poll_fd_can_read (self->poll, &self->serverpollfd)) {
      ShmClient *client;
      struct GstShmClient *gclient;

      GST_OBJECT_LOCK (self);
      client = sp_writer_accept_client (self->pipe);
      GST_OBJECT_UNLOCK (self);

      if (!client) {
        GST_ELEMENT_ERROR (self, RESOURCE, READ,
            ("Failed to read from shmsink"),
            ("Control socket returns wrong data"));
        return NULL;
      }

      gclient = g_slice_new (struct GstShmClient);
      gclient->client = client;
      gst_poll_fd_init (&gclient->pollfd);
      gclient->pollfd.fd = sp_writer_get_client_fd (client);
      gst_poll_add_fd (self->poll, &gclient->pollfd);
      gst_poll_fd_ctl_read (self->poll, &gclient->pollfd, TRUE);
      self->clients = g_list_prepend (self->clients, gclient);
      g_signal_emit (self, signals[SIGNAL_CLIENT_CONNECTED], 0,
          gclient->pollfd.fd);
      /* we need to call gst_poll_wait before calling gst_poll_* status
         functions on that new descriptor, so restart the loop, so _wait
         will have been called on all elements of self->poll, whether
         they have just been added or not. */
      timeout = 0;
      continue;
    }

  again:
    for (item = self->clients; item; item = item->next) {
      struct GstShmClient *gclient = item->data;

      if (gst_poll_fd_has_closed (self->poll, &gclient->pollfd)) {
        GST_WARNING_OBJECT (self, "One client is gone, closing");
        goto close_client;
      }

      if (gst_poll_fd_has_error (self->poll, &gclient->pollfd)) {
        GST_WARNING_OBJECT (self, "One client fd has error, closing");
        goto close_client;
      }

      if (gst_poll_fd_can_read (self->poll, &gclient->pollfd)) {
        int rv;
        gpointer tag = NULL;

        GST_OBJECT_LOCK (self);
        rv = sp_writer_recv (self->pipe, gclient->client, &tag);
        GST_OBJECT_UNLOCK (self);

        if (rv < 0) {
          GST_WARNING_OBJECT (self, "One client has read error,"
              " closing (retval: %d errno: %d)", rv, errno);
          goto close_client;
        }

        g_assert (rv == 0 || tag == NULL);

        if (rv == 0)
          gst_buffer_unref (tag);
      }
      continue;
    close_client:
      {
        GSList *list = NULL;
        GST_OBJECT_LOCK (self);
        sp_writer_close_client (self->pipe, gclient->client,
            (sp_buffer_free_callback) free_buffer_locked, (void **) &list);
        GST_OBJECT_UNLOCK (self);
        g_slist_free_full (list, (GDestroyNotify) gst_buffer_unref);
      }

      gst_poll_remove_fd (self->poll, &gclient->pollfd);
      self->clients = g_list_remove (self->clients, gclient);

      g_signal_emit (self, signals[SIGNAL_CLIENT_DISCONNECTED], 0,
          gclient->pollfd.fd);
      g_slice_free (struct GstShmClient, gclient);

      goto again;
    }

    g_cond_broadcast (&self->cond);
  }
Ejemplo n.º 16
0
static gboolean
gst_net_client_clock_start (GstNetClientClock * self)
{
  struct sockaddr_in servaddr, myaddr;
  socklen_t len;
  gint ret;
  GError *error;

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

  if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    goto no_socket;

  self->priv->sock.fd = ret;

  len = sizeof (myaddr);
  ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &myaddr, &len);
  if (ret < 0)
    goto getsockname_error;

  memset (&servaddr, 0, sizeof (servaddr));
  servaddr.sin_family = AF_INET;        /* host byte order */
  servaddr.sin_port = htons (self->port);       /* short, network byte order */

  GST_DEBUG_OBJECT (self, "socket opened on UDP port %hd",
      ntohs (servaddr.sin_port));

  if (!inet_aton (self->address, &servaddr.sin_addr))
    goto bad_address;

  self->servaddr = g_malloc (sizeof (struct sockaddr_in));
  memcpy (self->servaddr, &servaddr, sizeof (servaddr));

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

  gst_poll_add_fd (self->priv->fdset, &self->priv->sock);
  gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE);

  self->thread = g_thread_create (gst_net_client_clock_thread, self, TRUE,
      &error);
  if (!self->thread)
    goto no_thread;

  return TRUE;

  /* ERRORS */
no_socket:
  {
    GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    return FALSE;
  }
getsockname_error:
  {
    GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    return FALSE;
  }
bad_address:
  {
    GST_ERROR_OBJECT (self, "inet_aton failed %d: %s (%d)", ret,
        g_strerror (errno), errno);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    return FALSE;
  }
no_thread:
  {
    GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
    close (self->priv->sock.fd);
    self->priv->sock.fd = -1;
    g_free (self->servaddr);
    self->servaddr = NULL;
    g_error_free (error);
    return FALSE;
  }
}
Ejemplo n.º 17
0
static gpointer
pollthread_func (gpointer data)
{
  GstShmSink *self = GST_SHM_SINK (data);
  GList *item;

  while (!self->stop) {

    if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0)
      return NULL;

    if (self->stop)
      return NULL;

    if (gst_poll_fd_has_closed (self->poll, &self->serverpollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed read from shmsink"),
          ("Control socket has closed"));
      return NULL;
    }

    if (gst_poll_fd_has_error (self->poll, &self->serverpollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsink"),
          ("Control socket has error"));
      return NULL;
    }

    if (gst_poll_fd_can_read (self->poll, &self->serverpollfd)) {
      ShmClient *client;
      struct GstShmClient *gclient;

      GST_OBJECT_LOCK (self);
      client = sp_writer_accept_client (self->pipe);
      GST_OBJECT_UNLOCK (self);

      if (!client) {
        GST_ELEMENT_ERROR (self, RESOURCE, READ,
            ("Failed to read from shmsink"),
            ("Control socket returns wrong data"));
        return NULL;
      }

      gclient = g_slice_new (struct GstShmClient);
      gclient->client = client;
      gst_poll_fd_init (&gclient->pollfd);
      gclient->pollfd.fd = sp_writer_get_client_fd (client);
      gst_poll_add_fd (self->poll, &gclient->pollfd);
      gst_poll_fd_ctl_read (self->poll, &gclient->pollfd, TRUE);
      self->clients = g_list_prepend (self->clients, gclient);
      g_signal_emit (self, signals[SIGNAL_CLIENT_CONNECTED], 0,
          gclient->pollfd.fd);
    }

  again:
    for (item = self->clients; item; item = item->next) {
      struct GstShmClient *gclient = item->data;

      if (gst_poll_fd_has_closed (self->poll, &gclient->pollfd)) {
        GST_WARNING_OBJECT (self, "One client is gone, closing");
        goto close_client;
      }

      if (gst_poll_fd_has_error (self->poll, &gclient->pollfd)) {
        GST_WARNING_OBJECT (self, "One client fd has error, closing");
        goto close_client;
      }

      if (gst_poll_fd_can_read (self->poll, &gclient->pollfd)) {
        int rv;

        GST_OBJECT_LOCK (self);
        rv = sp_writer_recv (self->pipe, gclient->client);
        GST_OBJECT_UNLOCK (self);

        if (rv < 0) {
          GST_WARNING_OBJECT (self, "One client has read error,"
              " closing (retval: %d errno: %d)", rv, errno);
          goto close_client;
        }
      }
      continue;
    close_client:
      GST_OBJECT_LOCK (self);
      sp_writer_close_client (self->pipe, gclient->client);
      GST_OBJECT_UNLOCK (self);

      gst_poll_remove_fd (self->poll, &gclient->pollfd);
      self->clients = g_list_remove (self->clients, gclient);

      g_signal_emit (self, signals[SIGNAL_CLIENT_DISCONNECTED], 0,
          gclient->pollfd.fd);
      g_slice_free (struct GstShmClient, gclient);

      goto again;
    }

    g_cond_broadcast (self->cond);
  }
Ejemplo n.º 18
0
static void
mess_some_more (void)
{
  GList *walk;
  gint random;
  gint removed = 0;

  g_mutex_lock (fdlock);

  for (walk = fds; walk;) {
    GstPollFD *fd = (GstPollFD *) walk->data;

    walk = g_list_next (walk);

    random = (gint) (10.0 * rand () / (RAND_MAX + 1.0));
    switch (random) {
      case 0:
      {
        /*
           GstPollFD *newfd = g_new0 (GstPollFD, 1);

           gst_poll_add_fd (set, newfd);
           fds = g_list_prepend (fds, newfd);
         */
        break;
      }
      case 1:
        if ((gint) (10.0 * rand () / (RAND_MAX + 1.0)) < 2) {
          gst_poll_remove_fd (set, fd);
          fds = g_list_remove (fds, fd);
          g_free (fd);
          removed++;
        }
        break;

      case 2:
        gst_poll_fd_ctl_write (set, fd, TRUE);
        break;
      case 3:
        gst_poll_fd_ctl_write (set, fd, FALSE);
        break;
      case 4:
        gst_poll_fd_ctl_read (set, fd, TRUE);
        break;
      case 5:
        gst_poll_fd_ctl_read (set, fd, FALSE);
        break;

      case 6:
        gst_poll_fd_has_closed (set, fd);
        break;
      case 7:
        gst_poll_fd_has_error (set, fd);
        break;
      case 8:
        gst_poll_fd_can_read (set, fd);
        break;
      case 9:
        gst_poll_fd_can_write (set, fd);
        break;
      default:
        g_assert_not_reached ();
        break;
    }
  }
  if (g_list_length (fds) < 900) {
    random = removed + (gint) (2.0 * rand () / (RAND_MAX + 1.0));
    while (random) {
      GstPollFD *newfd = g_new0 (GstPollFD, 1);

      gst_poll_add_fd (set, newfd);
      fds = g_list_prepend (fds, newfd);
      random--;
    }
  }

  g_mutex_unlock (fdlock);
}
static void
handle_transfer (GstCurlBaseSink * sink)
{
  GstCurlBaseSinkClass *klass = GST_CURL_BASE_SINK_GET_CLASS (sink);
  gint retval;
  gint activated_fds;
  gint running_handles;
  gint timeout;
  CURLMcode m_code;
  CURLcode e_code;

  GST_OBJECT_LOCK (sink);
  timeout = sink->timeout;
  GST_OBJECT_UNLOCK (sink);

  GST_DEBUG_OBJECT (sink, "handling transfers");

  /* Receiving CURLM_CALL_MULTI_PERFORM means that libcurl may have more data
     available to send or receive - call simply curl_multi_perform before
     poll() on more actions */
  do {
    m_code = curl_multi_perform (sink->multi_handle, &running_handles);
  } while (m_code == CURLM_CALL_MULTI_PERFORM);
  GST_DEBUG_OBJECT (sink, "running handles: %d", running_handles);

  while (running_handles && (m_code == CURLM_OK)) {
    if (klass->transfer_prepare_poll_wait) {
      klass->transfer_prepare_poll_wait (sink);
    }

    activated_fds = gst_poll_wait (sink->fdset, timeout * GST_SECOND);
    if (G_UNLIKELY (activated_fds == -1)) {
      if (errno == EAGAIN || errno == EINTR) {
        GST_DEBUG_OBJECT (sink, "interrupted by signal");
      } else if (errno == EBUSY) {
        GST_DEBUG_OBJECT (sink, "poll stopped");
        retval = GST_FLOW_EOS;

        GST_OBJECT_LOCK (sink);
        if (gst_curl_base_sink_has_buffered_data_unlocked (sink))
          GST_WARNING_OBJECT (sink,
              "discarding render data due to thread close flag");
        GST_OBJECT_UNLOCK (sink);

        goto fail;
      } else {
        sink->error = g_strdup_printf ("poll failed: %s", g_strerror (errno));
        retval = GST_FLOW_ERROR;
        goto fail;
      }
    } else if (G_UNLIKELY (activated_fds == 0)) {
      sink->error = g_strdup_printf ("poll timed out after %" GST_TIME_FORMAT,
          GST_TIME_ARGS (timeout * GST_SECOND));
      retval = GST_FLOW_ERROR;
      goto fail;
    }

    /* readable/writable sockets */
    do {
      m_code = curl_multi_perform (sink->multi_handle, &running_handles);
    } while (m_code == CURLM_CALL_MULTI_PERFORM);
    GST_DEBUG_OBJECT (sink, "running handles: %d", running_handles);
  }

  if (m_code != CURLM_OK) {
    sink->error = g_strdup_printf ("failed to write data: %s",
        curl_multi_strerror (m_code));
    retval = GST_FLOW_ERROR;
    goto fail;
  }

  /* problems still might have occurred on individual transfers even when
   * curl_multi_perform returns CURLM_OK */
  if ((e_code = gst_curl_base_sink_transfer_check (sink)) != CURLE_OK) {
    sink->error = g_strdup_printf ("failed to transfer data: %s",
        curl_easy_strerror (e_code));
    retval = GST_FLOW_ERROR;
    goto fail;
  }

  gst_curl_base_sink_got_response_notify (sink);

  GST_OBJECT_LOCK (sink);
  if (sink->socket_type == CURLSOCKTYPE_ACCEPT) {
    /* FIXME: remove this again once we can depend on libcurl > 7.44.0,
     * see https://github.com/bagder/curl/issues/405.
     */
    if (G_UNLIKELY (sink->fd.fd < 0)) {
      sink->error = g_strdup_printf ("unknown error");
      retval = GST_FLOW_ERROR;
      GST_OBJECT_UNLOCK (sink);
      goto fail;
    }
    if (!gst_poll_remove_fd (sink->fdset, &sink->fd)) {
      sink->error = g_strdup_printf ("failed to remove fd");
      retval = GST_FLOW_ERROR;
      GST_OBJECT_UNLOCK (sink);
      goto fail;
    }
    sink->fd.fd = -1;
  }
  GST_OBJECT_UNLOCK (sink);

  return;

fail:
  GST_OBJECT_LOCK (sink);
  if (sink->flow_ret == GST_FLOW_OK) {
    sink->flow_ret = retval;
  }
  GST_OBJECT_UNLOCK (sink);
  return;
}