You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Review feedback: the watcher was started as a goroutine with no exit
condition. It blocked on a futex forever, so a program that finished with
signals kept a thread parked on one for the rest of its life. Nothing
observable broke — the thread is idle and process exit tears it down —
but a loop with no way out is a property worth not having.
The watcher exists only to serve enabled signals, so that is now its
lifetime: enabledSignals tracks the set os/signal wants delivered, the
last signal_disable/signal_ignore stops the thread, and a later
signal_enable starts a fresh one.
Stopping sets the flag, bumps the futex value and wakes it. The bump
matters as much as the wake: Wait(0) returns immediately when the futex
is already non-zero, which closes the window between the store and a
watcher that is about to sleep. On the way out the watcher resets the
futex to 0 so the next one can block on it.
CAS loops rather than atomic.Uint32.Or/And — those methods are newer than
some of the Go versions TinyGo builds against.
Verified with a program that blocks on a channel (never time.Sleep, so
delivery can only come from the watcher): the signal arrives, signal.Stop
lets the thread exit, and a later signal.Notify starts a new watcher that
delivers again.
0 commit comments