Manual
Cancellation and cleanup
Cancel a coroutine, interrupt its wait, and run code when it ends.
Introduction#
phasync::cancel throws a CancelledException into a coroutine at its next wait; Frame::cancel does the same to every coroutine of a frame, deepest first. phasync::finally callbacks always run, cancellation included, and their own waits are shielded from it; phasync::shielded does the same for cleanup outside a finally block. See Advanced: Coroutines for the rules cancellation follows.
Examples#
- All examples of this topic – 8 with their output.
Reference#
phasync::finally– Registers $fn to run when the current coroutine ends, or when the nested run() it is in returns.phasync::cancel– Cancels a coroutine with a CancelledException.phasync::throw– Interrupts the wait of a suspended coroutine with $exception, once.phasync::signal– Suspends the current coroutine until one of $signals (POSIX signal numbers such as SIGTERM) arrives, and returns the one that did. Any number of coroutines may wait for the same signal: each is woken. The waiter runs as an ordinary coroutine afterwards, so it may await, write and close connections; the signal's handler only records it, and the event loop wakes the waiters between coroutines, never inside one. A signal that came before the wait began doesn't end it.phasync::onSignal– Run $handler the moment $signo arrives, inside the signal handler: with pcntl_async_signals(true) in the middle of whatever is executing, even a coroutine that never yields; otherwise when the event loop dispatches signals. For what must happen at that moment, such as logging where a stuck process is; it must not suspend (no await, sleep or phasync I/O). Coroutines in phasync::signal are woken for the same signal as well. phasync takes the signal over until the outermost phasync::run() returns (a previous pcntl_signal() handler is called as well, and put back then), so register it for a run.phasync::shutdown– Stop the program's coroutines: every coroutine but the caller, whatever frame it is in, gets $exception (a ShutdownException, which is a CancelledException) at its wait, as phasync::cancel() does, and has up to $window seconds to clean up: finally blocks, and phasync::finally() callbacks, which may wait. Returns how many are still running after that, for the caller to decide (for example to exit, dropping them).phasync::shielded– Run $fn out of every cancellation's reach: phasync::cancel(), Frame::cancel(), and phasync::shutdown() don't cut its waits short. A cancellation that comes meanwhile applies at the coroutine's first wait after $fn returns. For infrastructure that must finish what it started, such as a server ending a protocol cleanly while the application's coroutines stop; application code rarely needs it.CancelledException– Thrown in a coroutine whose wait was cancelled: with phasync::cancel(), or with its frame (Frame::cancel(), the frame's deadline, a deadlock).ShutdownException– Thrown into the coroutines of a run by phasync::shutdown(): the program is stopping. It is a CancelledException, so it behaves like one: the coroutine meets it at its wait, its finally blocks run, and cleanup that must wait belongs in phasync::finally(). Code that only needs to stop catches nothing, or CancelledException; code that must tell someone why catches this.