mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
Add runtime checks and a fallback if we can't get the thread scheduler settings
On Linux the sched_getattr syscall might be available at compile-time but not actually work at runtime (e.g. because an older kernel is running or valgrind is used). Instead of killing the process, return FALSE and handle this gracefully at runtime with some fallback code. Fixes https://gitlab.gnome.org/GNOME/glib/issues/2007
This commit is contained in:
parent
457ea97c75
commit
012660b8fa
@ -1162,7 +1162,7 @@ g_system_thread_free (GRealThread *thread)
|
||||
g_slice_free (GThreadPosix, pt);
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
|
||||
{
|
||||
/* FIXME: Implement the same for macOS and the BSDs so it doesn't go through
|
||||
@ -1202,11 +1202,18 @@ g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_sett
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error ("Failed to get thread scheduler attributes: %s", g_strerror (errsv));
|
||||
g_debug ("Failed to get thread scheduler attributes: %s", g_strerror (errsv));
|
||||
g_free (scheduler_settings->attr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (res == -1);
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -428,11 +428,13 @@ g_thread_win32_proxy (gpointer data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
|
||||
{
|
||||
HANDLE current_thread = GetCurrentThread ();
|
||||
scheduler_settings->thread_prio = GetThreadPriority (current_thread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GRealThread *
|
||||
|
@ -902,11 +902,12 @@ g_thread_new_internal (const gchar *name,
|
||||
name, func, data, error);
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
|
||||
{
|
||||
g_return_if_fail (scheduler_settings != NULL);
|
||||
g_system_thread_get_scheduler_settings (scheduler_settings);
|
||||
g_return_val_if_fail (scheduler_settings != NULL, FALSE);
|
||||
|
||||
return g_system_thread_get_scheduler_settings (scheduler_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,9 +114,9 @@ static gint max_unused_threads = 2;
|
||||
static gint kill_unused_threads = 0;
|
||||
static guint max_idle_time = 15 * 1000;
|
||||
|
||||
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS
|
||||
static GThreadSchedulerSettings shared_thread_scheduler_settings;
|
||||
#else
|
||||
static gboolean have_shared_thread_scheduler_settings = FALSE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Either thread or error are set in the end. Both transfer-full. */
|
||||
@ -127,7 +127,6 @@ typedef struct
|
||||
|
||||
static GCond spawn_thread_cond;
|
||||
static GAsyncQueue *spawn_thread_queue;
|
||||
#endif
|
||||
|
||||
static void g_thread_pool_queue_push_unlocked (GRealThreadPool *pool,
|
||||
gpointer data);
|
||||
@ -294,7 +293,6 @@ g_thread_pool_wait_for_new_task (GRealThreadPool *pool)
|
||||
return task;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GTHREAD_SCHEDULER_SETTINGS
|
||||
static gpointer
|
||||
g_thread_pool_spawn_thread (gpointer data)
|
||||
{
|
||||
@ -326,7 +324,6 @@ g_thread_pool_spawn_thread (gpointer data)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gpointer
|
||||
g_thread_pool_thread_proxy (gpointer data)
|
||||
@ -475,23 +472,26 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
|
||||
* providing them if supported by the GThread implementation or by
|
||||
* going via our helper thread.
|
||||
*/
|
||||
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS
|
||||
thread = g_thread_new_internal (name, g_thread_proxy, g_thread_pool_thread_proxy, pool, 0, &shared_thread_scheduler_settings, error);
|
||||
#else
|
||||
SpawnThreadData spawn_thread_data = { (GThreadPool *) pool, NULL, NULL };
|
||||
if (have_shared_thread_scheduler_settings)
|
||||
{
|
||||
thread = g_thread_new_internal (name, g_thread_proxy, g_thread_pool_thread_proxy, pool, 0, &shared_thread_scheduler_settings, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnThreadData spawn_thread_data = { (GThreadPool *) pool, NULL, NULL };
|
||||
|
||||
g_async_queue_lock (spawn_thread_queue);
|
||||
g_async_queue_lock (spawn_thread_queue);
|
||||
|
||||
g_async_queue_push_unlocked (spawn_thread_queue, &spawn_thread_data);
|
||||
g_async_queue_push_unlocked (spawn_thread_queue, &spawn_thread_data);
|
||||
|
||||
while (!spawn_thread_data.thread && !spawn_thread_data.error)
|
||||
g_cond_wait (&spawn_thread_cond, _g_async_queue_get_mutex (spawn_thread_queue));
|
||||
while (!spawn_thread_data.thread && !spawn_thread_data.error)
|
||||
g_cond_wait (&spawn_thread_cond, _g_async_queue_get_mutex (spawn_thread_queue));
|
||||
|
||||
thread = spawn_thread_data.thread;
|
||||
if (!thread)
|
||||
g_propagate_error (error, g_steal_pointer (&spawn_thread_data.error));
|
||||
g_async_queue_unlock (spawn_thread_queue);
|
||||
#endif
|
||||
thread = spawn_thread_data.thread;
|
||||
if (!thread)
|
||||
g_propagate_error (error, g_steal_pointer (&spawn_thread_data.error));
|
||||
g_async_queue_unlock (spawn_thread_queue);
|
||||
}
|
||||
}
|
||||
|
||||
if (thread == NULL)
|
||||
@ -605,13 +605,16 @@ g_thread_pool_new (GFunc func,
|
||||
*/
|
||||
if (!exclusive)
|
||||
{
|
||||
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS
|
||||
g_thread_get_scheduler_settings (&shared_thread_scheduler_settings);
|
||||
#else
|
||||
spawn_thread_queue = g_async_queue_new ();
|
||||
g_cond_init (&spawn_thread_cond);
|
||||
g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
|
||||
#endif
|
||||
if (g_thread_get_scheduler_settings (&shared_thread_scheduler_settings))
|
||||
{
|
||||
have_shared_thread_scheduler_settings = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawn_thread_queue = g_async_queue_new ();
|
||||
g_cond_init (&spawn_thread_cond);
|
||||
g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
G_UNLOCK (init);
|
||||
|
@ -74,7 +74,7 @@ void g_system_thread_free (GRealThread *thread);
|
||||
void g_system_thread_exit (void);
|
||||
void g_system_thread_set_name (const gchar *name);
|
||||
|
||||
void g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
|
||||
gboolean g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
|
||||
|
||||
/* gthread.c */
|
||||
GThread *g_thread_new_internal (const gchar *name,
|
||||
@ -85,7 +85,7 @@ GThread *g_thread_new_internal (const gchar *name,
|
||||
const GThreadSchedulerSettings *scheduler_settings,
|
||||
GError **error);
|
||||
|
||||
void g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
|
||||
gboolean g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
|
||||
|
||||
gpointer g_thread_proxy (gpointer thread);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user