static gboolean gst_shm_sink_stop (GstBaseSink * bsink) { GstShmSink *self = GST_SHM_SINK (bsink); self->stop = TRUE; gst_poll_set_flushing (self->poll, TRUE); if (self->allocator) gst_object_unref (self->allocator); self->allocator = NULL; g_thread_join (self->pollthread); self->pollthread = NULL; GST_DEBUG_OBJECT (self, "Stopping"); while (self->clients) { struct GstShmClient *client = self->clients->data; self->clients = g_list_remove (self->clients, client); sp_writer_close_client (self->pipe, client->client, (sp_buffer_free_callback) gst_buffer_unref, NULL); g_signal_emit (self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, client->pollfd.fd); g_slice_free (struct GstShmClient, client); } gst_poll_free (self->poll); self->poll = NULL; sp_writer_close (self->pipe, NULL, NULL); self->pipe = NULL; return TRUE; }
static gboolean shm_writer_client_fd_cb (GIOChannel *source, GIOCondition condition, gpointer data) { ShmWriterClientPair *pair = data; ShmWriterPrivate *priv = pair->self->priv; if (condition == G_IO_IN) { g_mutex_lock (priv->lock); if (sp_writer_recv (pair->self->priv->writer, pair->client) != 0) goto error_locked; g_mutex_unlock (priv->lock); } else if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { goto error; } return TRUE; error: g_mutex_lock (priv->lock); error_locked: if (priv->writer != NULL) sp_writer_close_client (priv->writer, pair->client); g_mutex_unlock (priv->lock); /* No need to destroy the source when the writer is destroyed. * We're destroying it here */ g_object_weak_unref (G_OBJECT (pair->self), shm_writer_destroy_source, g_main_current_source ()); return FALSE; }
void sp_close (ShmPipe * self) { if (self->main_socket >= 0) close (self->main_socket); if (self->socket_path) { unlink (self->socket_path); free (self->socket_path); } while (self->clients) sp_writer_close_client (self, self->clients); sp_dec (self); }
void sp_writer_close (ShmPipe * self, sp_buffer_free_callback callback, void *user_data) { if (self->main_socket >= 0) { shutdown (self->main_socket, SHUT_RDWR); close (self->main_socket); } if (self->socket_path) { unlink (self->socket_path); free (self->socket_path); } while (self->clients) sp_writer_close_client (self, self->clients, callback, user_data); sp_dec (self); }
void sp_close (ShmPipe * self) { if (self->main_socket >= 0) close (self->main_socket); if (self->socket_path) { unlink (self->socket_path); free (self->socket_path); } while (self->clients) sp_writer_close_client (self, self->clients); while (self->shm_area) { sp_shm_area_dec (self, self->shm_area); } spalloc_free (ShmPipe, self); }
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); }
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); }