summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <edward@centricular.com>2020-06-12 15:07:42 +0200
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2020-09-21 15:46:39 +0000
commitc33f859aa0cc411613c6ac7c63b413b2efde7fea (patch)
tree617a68e937a4a3cc21ececd59ad069548f1d093c
parentd04b27f4ec2835253ed33d522b93408b9f343ba1 (diff)
gst: Delay creation of threadpools
Since glib 2.64, gthreadpool will start waiting on a GCond immediately upon creation. This can cause issues if we fork *before* actually using the threadpool since we will then be signalling that GCond ... from another process and that will never work. Instead, delay creationg of thread pools until the very first time we need them. This introduces a minor (un-noticeable) delay when needing a new thread but fixes the issues for all users of GSTreamer that will call gst_init, then fork and actually start pipelines. See https://gitlab.gnome.org/GNOME/glib/-/issues/2131 for more context. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/634>
-rw-r--r--gst/gstelement.c22
-rw-r--r--gst/gsttask.c33
2 files changed, 35 insertions, 20 deletions
diff --git a/gst/gstelement.c b/gst/gstelement.c
index 64aa39a04f..b34608570e 100644
--- a/gst/gstelement.c
+++ b/gst/gstelement.c
@@ -152,6 +152,7 @@ static void gst_element_call_async_func (gpointer data, gpointer user_data);
static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
+static GMutex _element_pool_lock;
static GThreadPool *gst_element_pool = NULL;
/* this is used in gstelementfactory.c:gst_element_register() */
@@ -187,19 +188,22 @@ gst_element_get_type (void)
return gst_element_type;
}
-static void
+static GThreadPool *
gst_element_setup_thread_pool (void)
{
GError *err = NULL;
+ GThreadPool *pool;
GST_DEBUG ("creating element thread pool");
- gst_element_pool =
+ pool =
g_thread_pool_new ((GFunc) gst_element_call_async_func, NULL, -1, FALSE,
&err);
if (err != NULL) {
g_critical ("could not alloc threadpool %s", err->message);
g_clear_error (&err);
}
+
+ return pool;
}
static void
@@ -266,8 +270,6 @@ gst_element_class_init (GstElementClass * klass)
klass->set_context = GST_DEBUG_FUNCPTR (gst_element_set_context_default);
klass->elementfactory = NULL;
-
- gst_element_setup_thread_pool ();
}
static void
@@ -3728,16 +3730,22 @@ gst_element_call_async (GstElement * element, GstElementCallAsyncFunc func,
async_data->user_data = user_data;
async_data->destroy_notify = destroy_notify;
- g_thread_pool_push (gst_element_pool, async_data, NULL);
+ g_mutex_lock (&_element_pool_lock);
+ if (G_UNLIKELY (gst_element_pool == NULL))
+ gst_element_pool = gst_element_setup_thread_pool ();
+ g_thread_pool_push ((GThreadPool *) gst_element_pool, async_data, NULL);
+ g_mutex_unlock (&_element_pool_lock);
}
void
_priv_gst_element_cleanup (void)
{
+ g_mutex_lock (&_element_pool_lock);
if (gst_element_pool) {
- g_thread_pool_free (gst_element_pool, FALSE, TRUE);
- gst_element_setup_thread_pool ();
+ g_thread_pool_free ((GThreadPool *) gst_element_pool, FALSE, TRUE);
+ gst_element_pool = NULL;
}
+ g_mutex_unlock (&_element_pool_lock);
}
GstStructure *
diff --git a/gst/gsttask.c b/gst/gsttask.c
index 30f25fef8f..51e6d9f9e9 100644
--- a/gst/gsttask.c
+++ b/gst/gsttask.c
@@ -145,6 +145,8 @@ static void gst_task_func (GstTask * task);
static GMutex pool_lock;
+static GstTaskPool *_global_task_pool = NULL;
+
#define _do_init \
{ \
GST_DEBUG_CATEGORY_INIT (task_debug, "task", 0, "Processing tasks"); \
@@ -153,19 +155,18 @@ static GMutex pool_lock;
G_DEFINE_TYPE_WITH_CODE (GstTask, gst_task, GST_TYPE_OBJECT,
G_ADD_PRIVATE (GstTask) _do_init);
+/* Called with pool_lock */
static void
-init_klass_pool (GstTaskClass * klass)
+ensure_klass_pool (GstTaskClass * klass)
{
- g_mutex_lock (&pool_lock);
- if (klass->pool) {
- gst_task_pool_cleanup (klass->pool);
- gst_object_unref (klass->pool);
+ if (G_UNLIKELY (_global_task_pool == NULL)) {
+ _global_task_pool = gst_task_pool_new ();
+ gst_task_pool_prepare (_global_task_pool, NULL);
+
+ /* Classes are never destroyed so this ref will never be dropped */
+ GST_OBJECT_FLAG_SET (_global_task_pool, GST_OBJECT_FLAG_MAY_BE_LEAKED);
}
- klass->pool = gst_task_pool_new ();
- /* Classes are never destroyed so this ref will never be dropped */
- GST_OBJECT_FLAG_SET (klass->pool, GST_OBJECT_FLAG_MAY_BE_LEAKED);
- gst_task_pool_prepare (klass->pool, NULL);
- g_mutex_unlock (&pool_lock);
+ klass->pool = _global_task_pool;
}
static void
@@ -176,8 +177,6 @@ gst_task_class_init (GstTaskClass * klass)
gobject_class = (GObjectClass *) klass;
gobject_class->finalize = gst_task_finalize;
-
- init_klass_pool (klass);
}
static void
@@ -197,6 +196,7 @@ gst_task_init (GstTask * task)
/* use the default klass pool for this task, users can
* override this later */
g_mutex_lock (&pool_lock);
+ ensure_klass_pool (klass);
task->priv->pool = gst_object_ref (klass->pool);
g_mutex_unlock (&pool_lock);
}
@@ -378,7 +378,14 @@ gst_task_cleanup_all (void)
GstTaskClass *klass;
if ((klass = g_type_class_peek (GST_TYPE_TASK))) {
- init_klass_pool (klass);
+ if (klass->pool) {
+ g_mutex_lock (&pool_lock);
+ gst_task_pool_cleanup (klass->pool);
+ gst_object_unref (klass->pool);
+ klass->pool = NULL;
+ _global_task_pool = NULL;
+ g_mutex_unlock (&pool_lock);
+ }
}
/* GstElement owns a GThreadPool */