| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Runtime.Server.Halt
Description
The local-development immediate-halt wiring: an interactive session's
"quit now" key, inert outside a terminal. Ecluse.Runtime.Server's runWarp
wraps the whole run in withInteractiveHalt.
Synopsis
- data InteractiveHalt = InteractiveHalt {
- haltOnInteractive :: IO Bool
- awaitHaltSignal :: IO ()
- halt :: IO ()
- defaultInteractiveHalt :: InteractiveHalt
- withInteractiveHalt :: InteractiveHalt -> IO a -> IO a
Documentation
data InteractiveHalt Source #
The local-development immediate-halt wiring, as three injection points so its logic is exercised without a real terminal. It exists only to give an interactive session a "quit now" key: when the server is attached to a TTY, closing standard input (Ctrl-D) forces an immediate process exit, aborting any in-progress drain -- the same hard-stop a second Ctrl-C gives, but on the dev's deliberate signal.
It is inert outside an interactive terminal: in production standard input is a
non-TTY or closed, haltOnInteractive returns False, and no watcher is installed,
so the signal-driven graceful lifecycle is completely untouched. The TTY guard is
what enforces that zero-production-impact contract (see withInteractiveHalt).
Constructors
| InteractiveHalt | |
Fields
| |
defaultInteractiveHalt :: InteractiveHalt Source #
The real local-dev halt: armed only when standard input is a terminal
(hIsTerminalDevice), fired by end-of-input on standard input (Ctrl-D), and
halting via exitImmediately -- an immediate _exit that bypasses the graceful
drain, mirroring a second Ctrl-C. The exit status (130) is the conventional
"terminated from the terminal" code.
withInteractiveHalt :: InteractiveHalt -> IO a -> IO a Source #
Run an action with the local-dev immediate-halt watcher armed __only when
interactive__. If haltOnInteractive is True, a watcher runs alongside the action
for exactly its lifetime (withAsync, so it is torn down when the action returns or
is cancelled -- it never lingers); the watcher blocks on awaitHaltSignal and, when
that returns, runs halt. If False -- the production case -- the action runs alone,
with no watcher and no extra thread, so nothing about the graceful lifecycle changes.