This needs to be undefined behavior as we do not have the possibilities in PHP (i.e. the language and functions don't give us the power) to distinguish properly whether a signal is already installed or not
Also, when we try to set a handler for a signal we've already installed a signal elsewhere, the second onSignal() call will lead implementations to override the original handler (on the system level, with signal()/sigaction())
Ultimately some extensions just flat out emit a warning in that case (e.g. libev).
Thus, we cannot control what happens and hence this needs to be specified as undefined behavior.
Delaying activation of watchers to the next tick guarantees consistent behavior between all implementations.
Additionally it eliminates the following problem:
- Two defer()'s are set up with the first one immediately disabled
- Second defer()'s callback is called and enables the first defer()'s watcher
- Executes defer() in same tick or next tick?
If the answer is same tick, what happens in the following scenario:
- An immediately disabled defer() and a delay($msDelay = 0) are set up
- The delay()'s callback enables the defer()'s watcher
- Executes defer() callback in same tick or next tick?
Doing it in same tick violates the requirement that defers are called before any other watchers in the same tick.
We get similar problems with e.g. delay() and repeat() (if their timer all expired now, but we require order to be preserved).
Thus we need to pretty much delay the activation of enable() to the next tick to avoid potential ambiguity or different behaviors depending on when exactly the enable() or watcher registration happened.
Using a short delay was sometimes not long enough to ensure that $sig2 was actually enabled before the signal was sent. Using a defer after enabling pushes the call to posix_kill() to the next tick.