From 3e3a6be4023189b2d637beda240e23fa9e856810 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Mon, 16 Jan 2023 11:46:09 -0500 Subject: rts: Fix data-race in hs_init_ghc As noticed by @Terrorjack, `hs_init_ghc` previously used non-atomic increment/decrement on the RTS's initialization count. This may go wrong in a multithreaded program which initializes the runtime multiple times. Closes #22756. --- rts/RtsStartup.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index 5cb94c71e8..cfbd0421f5 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -68,7 +68,7 @@ #endif // Count of how many outstanding hs_init()s there have been. -static int hs_init_count = 0; +static StgWord hs_init_count = 0; static bool rts_shutdown = false; #if defined(mingw32_HOST_OS) @@ -242,8 +242,9 @@ hs_init_with_rtsopts(int *argc, char **argv[]) void hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config) { - hs_init_count++; - if (hs_init_count > 1) { + // N.B. atomic_inc returns the new value. + StgWord init_count = atomic_inc(&hs_init_count, 1); + if (init_count > 1) { // second and subsequent inits are ignored return; } @@ -452,15 +453,17 @@ hs_exit_(bool wait_foreign) { uint32_t g, i; - if (hs_init_count <= 0) { - errorBelch("warning: too many hs_exit()s"); + // N.B. atomic_dec returns the new value. + StgInt init_count = (StgInt)atomic_dec(&hs_init_count); + if (init_count > 0) { + // ignore until it's the last one return; } - hs_init_count--; - if (hs_init_count > 0) { - // ignore until it's the last one + if (init_count < 0) { + errorBelch("warning: too many hs_exit()s"); return; } + rts_shutdown = true; /* start timing the shutdown */ -- cgit v1.2.1