Matthew Pickering pushed to branch wip/fix-eventlog-flush-deadlock at Glasgow Haskell Compiler / GHC

Commits:

2 changed files:

Changes:

  • rts/eventlog/EventLog.c
    ... ... @@ -491,13 +491,7 @@ endEventLogging(void)
    491 491
     
    
    492 492
         eventlog_enabled = false;
    
    493 493
     
    
    494
    -    // Flush all events remaining in the buffers.
    
    495
    -    //
    
    496
    -    // N.B. Don't flush if shutting down: this was done in
    
    497
    -    // finishCapEventLogging and the capabilities have already been freed.
    
    498
    -    if (getSchedState() != SCHED_SHUTTING_DOWN) {
    
    499
    -        flushEventLog(NULL);
    
    500
    -    }
    
    494
    +    flushEventLog(NULL);
    
    501 495
     
    
    502 496
         ACQUIRE_LOCK(&eventBufMutex);
    
    503 497
     
    
    ... ... @@ -1626,15 +1620,24 @@ void flushEventLog(Capability **cap USED_IF_THREADS)
    1626 1620
             return;
    
    1627 1621
         }
    
    1628 1622
     
    
    1623
    +    // N.B. Don't flush if shutting down: this was done in
    
    1624
    +    // finishCapEventLogging and the capabilities have already been freed.
    
    1625
    +    // This can also race against the shutdown if the flush is triggered by the
    
    1626
    +    // ticker thread. (#26573)
    
    1627
    +    if (getSchedState() == SCHED_SHUTTING_DOWN) {
    
    1628
    +      return;
    
    1629
    +    }
    
    1630
    +
    
    1629 1631
         ACQUIRE_LOCK(&eventBufMutex);
    
    1630 1632
         printAndClearEventBuf(&eventBuf);
    
    1631 1633
         RELEASE_LOCK(&eventBufMutex);
    
    1632 1634
     
    
    1633 1635
     #if defined(THREADED_RTS)
    
    1634
    -    Task *task = getMyTask();
    
    1636
    +    Task *task = newBoundTask();
    
    1635 1637
         stopAllCapabilitiesWith(cap, task, SYNC_FLUSH_EVENT_LOG);
    
    1636 1638
         flushAllCapsEventsBufs();
    
    1637 1639
         releaseAllCapabilities(getNumCapabilities(), cap ? *cap : NULL, task);
    
    1640
    +    exitMyTask();
    
    1638 1641
     #else
    
    1639 1642
         flushLocalEventsBuf(getCapability(0));
    
    1640 1643
     #endif
    

  • testsuite/tests/rts/all.T
    ... ... @@ -2,6 +2,11 @@ test('testblockalloc',
    2 2
          [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')],
    
    3 3
          compile_and_run, [''])
    
    4 4
     
    
    5
    +test('numeric_version_eventlog_flush',
    
    6
    +     [ignore_stdout],
    
    7
    +     run_command,
    
    8
    +     ['{compiler} --numeric-version +RTS -l --eventlog-flush-interval=1 -RTS'])
    
    9
    +
    
    5 10
     test('testmblockalloc',
    
    6 11
          [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0 -xr0.125T'),
    
    7 12
           when(arch('wasm32'), skip)], # MBlocks can't be freed on wasm32, see Note [Megablock allocator on wasm] in rts