[glib: 1/3] Add runtime checks and a fallback if we can't get the thread scheduler settings



commit 012660b8fa47dcb81fee3300e0de94e7c0639da1
Author: Sebastian Dröge <sebastian centricular com>
Date:   Sat Jan 18 13:23:30 2020 +0200

    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

 glib/gthread-posix.c  | 11 +++++++++--
 glib/gthread-win32.c  |  4 +++-
 glib/gthread.c        |  7 ++++---
 glib/gthreadpool.c    | 53 +++++++++++++++++++++++++++------------------------
 glib/gthreadprivate.h |  4 ++--
 5 files changed, 46 insertions(+), 33 deletions(-)
---
diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c
index 2f26e5831..9df6d7994 100644
--- a/glib/gthread-posix.c
+++ b/glib/gthread-posix.c
@@ -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
 }
 
diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c
index 8bc4f3a4b..1de044851 100644
--- a/glib/gthread-win32.c
+++ b/glib/gthread-win32.c
@@ -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 *
diff --git a/glib/gthread.c b/glib/gthread.c
index 569fbeec3..73138cb34 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -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);
 }
 
 /**
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
index ce0350a69..dd6546be4 100644
--- a/glib/gthreadpool.c
+++ b/glib/gthreadpool.c
@@ -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);
diff --git a/glib/gthreadprivate.h b/glib/gthreadprivate.h
index 4842a1e9f..afbe75934 100644
--- a/glib/gthreadprivate.h
+++ b/glib/gthreadprivate.h
@@ -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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]