
#8684: hWaitForInput cannot be interrupted by async exceptions on unix -------------------------------------+------------------------------------- Reporter: nh2 | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Core Libraries | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: 13497, 13525 | Blocking: Related Tickets: #12912, #13525 | Differential Rev(s): Phab:D42 Wiki Page: | -------------------------------------+------------------------------------- Comment (by nh2): As part of the review of my patch in https://phabricator.haskell.org/D42, I have gathered some information of how the timer signal is implemented. Since that may be a useful by itself, I post it here. It is as of commit `a1950e6`, and, since not much of this has changed since the last release, also of GHC 8.2. # How the timer signal is implemented In general, the tick callbacks go like this to do context switching: {{{ handle_tick() contextSwitchAllCapabilities() for all capabilities: contextSwitchCapability() stopCapability() cap->r.rHpLim = NULL; // makes the heap check fail also sets `cap->interrupt = 1;` }}} Methods used on the various platforms: {{{ - POSIX (method selected in `posix/Itimer.c`) - Linux, threaded RTS -> timer_create() if it exists, otherwise setitimer() - Linux, non-threaded, >= 2.6.25 -> pthread with timerfd - Linux, non-threaded, < 2.6.25 -> pthread without timerfd - Darwin -> pthread without timerfd - iOS -> pthread without timerfd - Windows (`win32/Ticker.c`) - Windows -> CreateTimerQueueTimer() }}} Notably the Darwin and iOS implementations use a pthread even for the non- threaded RTS! Relevant trac issues about the above methods: * #1933 - [https://ghc.haskell.org/trac/ghc/ticket/1933 Zero times in profiling with GHC-6.8.1] -- This added autoconf-based detection of `timer_create()` on Linux. * #10840 - [https://ghc.haskell.org/trac/ghc/ticket/10840 Periodic alarm signals can cause a retry loop to get stuck] -- This added the pthread-based implementations. Method implementation locations: {{{ - pthread with timerfd -> `itimer/Pthread.c` - pthread without timerfd (sleep loop) -> `itimer/Pthread.c` - timer_create() -> `itimer/TimerCreate.c` - setitimer() -> `itimer/Setitimer.c` }}} How the implementations work: - pthread with timerfd - A pthread is started that runs a loop reading from the timerfd. No SIGVTALRM is used. When the timerfd ticks, that thread wakes up and calls handle_tick(). - pthread without timerfd - A pthread is started that runs a loop running `sleep(itimer_interval)`. No SIGVTALRM is used. When that thread finishes the sleep, it calls handle_tick(). - timer_create() - A SIGVTALRM signal handler is set up that `handle_tick()`. Then timer_create() is called to set up a SIGVTALRM signal occurring regularly, using the `ITIMER_REAL` real-time clock. The SIGVTALRM signal occurring will EINTR all system calls of all threads of the process. - `setitimer()` - A SIGVTALRM signal handler is set up that `handle_tick()`. Then `setitimer()` is called to set up a SIGVTALRM signal occurring regularly, using the `CLOCK_ID` clock, which is `CLOCK_MONOTONIC` if available and `CLOCK_REALTIME` otherwise. The SIGVTALRM signal occurring will EINTR all system calls of all threads of the process. - `CreateTimerQueueTimer()` - `CreateTimerQueueTimer()` is set up to call `tick_callback()` which calls `tick_proc = handle_tick()` regularly. The option `WT_EXECUTEINTIMERTHREAD` is passed which results in "callback function is invoked by the timer thread itself". There are a couple issues with it: 1. The period is set to `TimeToUS(tick_interval) / 1000` milliseconds, which becomes 0 if less than a millisecond is chosen. `CreateTimerQueueTimer()` does not document what happens if a 0-period is given. It might busy-poll, but it's not documented, so who knows? 2. A comment in the code remarks that this timer has a maximum accuracy of 15ms on Windows 7, and even worse on older platforms. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8684#comment:29 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler