Ticket #637 (closed bug: fixed)

Opened 8 years ago

Last modified 4 years ago

Ctrl-Break handler doesn't work in forked threads in "-threaded" RTS

Reported by: bulatz@… Owned by: simonmar
Priority: high Milestone: 6.6.1
Component: Runtime System Version: 6.4.1
Keywords: Cc: Bulat.Ziganshin@…
Operating System: Windows Architecture: Unknown/Multiple
Type of failure: Difficulty: Moderate (less than a day)
Test Case: Blocked By:
Blocking: Related Tickets:

Description (last modified by simonmar) (diff)

The following program demonstrates bug in 6.4.1 (6.4.0 was ok). if you compile it with "-threaded", run and press Ctrl-Break, you will see message "main.EXE: <stdin>: hGetLine: end of file" and program blocks (because forked thread is dead). the problem is that installed ctrl-break handler don't called in forked threads

if you compile program without "-threaded" or with 6.4.0, it works as expected - pressing Ctrl-Break runs my handler so you will see "Break! main.EXE: thread killed" message

import Control.Concurrent
import Control.Exception
import GHC.ConsoleHandler

handleCtrlBreak action = do
  myThread <- myThreadId
  let onBreak event = do
        putStrLn " ^Break!"
        killThread myThread
  bracket (installHandler$ Catch onBreak) (installHandler) $  \oldHandler -> do
    action

main =  do
  handleCtrlBreak $ do
    x <- newEmptyMVar
    forkIO$ do a <- getLine
               print a
               putMVar x ()
               return ()
    takeMVar x
    return ()

Change History

Changed 7 years ago by bulatz@…

  • component changed from Compiler to Runtime System

Changed 7 years ago by guest

The following program demonstrates bug in 6.4.1 (6.4.0 was ok).

if you compile it with "-threaded", run and press Ctrl-Break, you will see message "main.EXE: <stdin>: hGetLine: end of file" and program blocks (because forked thread is dead). the problem is that installed ctrl-break handler don't called in forked threads

if you compile program without "-threaded" or with 6.4.0, it works as expected - pressing Ctrl-Break runs my handler so you will see "Break! main.EXE: thread killed" message

 import Control.Concurrent
 import Control.Exception
 import GHC.ConsoleHandler

 handleCtrlBreak action = do
   myThread <- myThreadId
   let onBreak event = do
         putStrLn " ^Break!"
         killThread myThread
   bracket (installHandler$ Catch onBreak) (installHandler) $  \oldHandler -> do
     action

 main =  do
   handleCtrlBreak $ do
     x <- newEmptyMVar
     forkIO$ do a <- getLine
                print a
                putMVar x ()
                return ()
     takeMVar x
     return ()

Changed 7 years ago by simonpj

  • owner set to simonmar

Changed 7 years ago by simonmar

  • description modified (diff)
  • milestone set to 6.4.2

Changed 7 years ago by simonmar

  • difficulty changed from Unknown to Moderate (1 day)
  • os changed from Unknown to Windows
  • milestone changed from 6.4.2 to 6.6

Verified. I'm not sure why it worked in 6.4.0, perhaps it was by accident. The console handler function, generic_handler in ConsoleHandler?.c, has no way to wake up an RTS thread - it tries to ping the async IO system, but async IO isn't used in -threaded on Windows now (since 6.2).

The proper fix for this is for Windows to use the I/O manager with -threaded, as Unix does. On Unix, when a signal arrives, a byte is sent down a pipe to the I/O manager thread which launches the appropriate signal handler.

I'll punt on this for 6.4.2.

Changed 7 years ago by guest

  • cc Bulat.Ziganshin@… added

Changed 7 years ago by simonmar

  • milestone changed from 6.6 to 6.6.1

Punt.

Changed 7 years ago by simonmar

  • priority changed from normal to high

Changed 7 years ago by simonmar

  • status changed from new to closed
  • resolution set to fixed

Fixed.

Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple

Changed 4 years ago by simonmar

  • difficulty changed from Moderate (1 day) to Moderate (less than a day)
Note: See TracTickets for help on using tickets.