From 37ad8856fd97dfdbd334e88300ff661f772b8110 Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Wed, 21 Jul 2021 11:18:14 +0200
Subject: [PATCH] RTS: try to fix timer races

* Pthread based timer was initialized started while some other parts of
  the RTS assume it is initialized stopped, e.g. in hs_init_ghc:

     /* Start the "ticker" and profiling timer but don't start until the
     * scheduler is up. However, the ticker itself needs to be initialized
     * before the scheduler to ensure that the ticker mutex is initialized as
     * moreCapabilities will attempt to acquire it.
     */

* after a fork, don't start the timer before the IOManager is
  initialized: the timer handler (handle_tick) might call wakeUpRts to
  perform an idle GC, which calls wakeupIOManager/ioManagerWakeup

Found while debugging #18033/#20132 but I couldn't confirm if it fixes
them.

(cherry picked from commit 5f3991c7cab8ccc9ab8daeebbfce57afbd9acc33)
---
 rts/Schedule.c             | 5 ++++-
 rts/posix/itimer/Pthread.c | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/rts/Schedule.c b/rts/Schedule.c
index 061de639b28f..204f356554e5 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -2157,7 +2157,6 @@ forkProcess(HsStablePtr *entry
         // On Unix, all timers are reset in the child, so we need to start
         // the timer again.
         initTimer();
-        startTimer();
 
         // TODO: need to trace various other things in the child
         // like startup event, capabilities, process info etc
@@ -2167,6 +2166,10 @@ forkProcess(HsStablePtr *entry
         ioManagerStartCap(&cap);
 #endif
 
+        // start timer after the IOManager is initialized
+        // (the idle GC may wake up the IOManager)
+        startTimer();
+
         // Install toplevel exception handlers, so interruption
         // signal will be sent to the main thread.
         // See #12903
diff --git a/rts/posix/itimer/Pthread.c b/rts/posix/itimer/Pthread.c
index 73b1eba5def6..738e5ec469cc 100644
--- a/rts/posix/itimer/Pthread.c
+++ b/rts/posix/itimer/Pthread.c
@@ -168,7 +168,7 @@ void
 initTicker (Time interval, TickProc handle_tick)
 {
     itimer_interval = interval;
-    stopped = false;
+    stopped = true;
     exited = false;
 #if defined(HAVE_SIGNAL_H)
     sigset_t mask, omask;
-- 
GitLab