Fix initialization logic of GThreadPool if the first created pool is an exclusive one

Previously we would only ever run the initialization code once, but part
of it only if a non-exclusive pool was created. This caused the shared
state to be inconsistent if the first pool to be created was exclusive
and the second non-exclusive.

Fixes https://gitlab.gnome.org/GNOME/glib/issues/2012
This commit is contained in:
Sebastian Dröge 2020-01-25 11:08:22 +02:00
parent ac0c0b5b28
commit 78bae85d21

View File

@ -579,42 +579,41 @@ g_thread_pool_new (GFunc func,
G_LOCK (init); G_LOCK (init);
if (!unused_thread_queue) if (!unused_thread_queue)
{
unused_thread_queue = g_async_queue_new (); unused_thread_queue = g_async_queue_new ();
/* For the very first non-exclusive thread-pool we remember the thread
* scheduler settings of the thread creating the pool, if supported by /* For the very first non-exclusive thread-pool we remember the thread
* the GThread implementation. This is then used for making sure that * scheduler settings of the thread creating the pool, if supported by
* all threads created on the non-exclusive thread-pool have the same * the GThread implementation. This is then used for making sure that
* scheduler settings, and more importantly don't just inherit them * all threads created on the non-exclusive thread-pool have the same
* from the thread that just happened to push a new task and caused * scheduler settings, and more importantly don't just inherit them
* a new thread to be created. * from the thread that just happened to push a new task and caused
* * a new thread to be created.
* Not doing so could cause real-time priority threads or otherwise *
* threads with problematic scheduler settings to be part of the * Not doing so could cause real-time priority threads or otherwise
* non-exclusive thread-pools. * threads with problematic scheduler settings to be part of the
* * non-exclusive thread-pools.
* If this is not supported by the GThread implementation then we here *
* start a thread that will inherit the scheduler settings from this * If this is not supported by the GThread implementation then we here
* very thread and whose only purpose is to spawn new threads with the * start a thread that will inherit the scheduler settings from this
* same settings for use by the non-exclusive thread-pools. * very thread and whose only purpose is to spawn new threads with the
* * same settings for use by the non-exclusive thread-pools.
* *
* For non-exclusive thread-pools this is not required as all threads *
* are created immediately below and are running forever, so they will * For non-exclusive thread-pools this is not required as all threads
* automatically inherit the scheduler settings from this very thread. * are created immediately below and are running forever, so they will
*/ * automatically inherit the scheduler settings from this very thread.
if (!exclusive) */
if (!exclusive && !have_shared_thread_scheduler_settings && !spawn_thread_queue)
{
if (g_thread_get_scheduler_settings (&shared_thread_scheduler_settings))
{ {
if (g_thread_get_scheduler_settings (&shared_thread_scheduler_settings)) have_shared_thread_scheduler_settings = TRUE;
{ }
have_shared_thread_scheduler_settings = TRUE; else
} {
else spawn_thread_queue = g_async_queue_new ();
{ g_cond_init (&spawn_thread_cond);
spawn_thread_queue = g_async_queue_new (); g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
g_cond_init (&spawn_thread_cond);
g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
}
} }
} }
G_UNLOCK (init); G_UNLOCK (init);