The upgrader has fairly complex logic and locking behaviour. The Stop() method
is more involved than it should be, since we need to clean up if no upgrade
happened.
Moving the code into a goroutine makes the flow and invariants easier to
understand.
There is one semantic change: Upgrade() does not return an error if the parent
unexpectedly writes to the shutdown pipe. The likelihood of this happening
is low, and it's not clear how severe that problem would be. By not rejecting
upgrade requests we allow users to fix such problems without having to do
a full restart.
The upgrader has fairly complex logic and locking behaviour. The Stop() method is more involved than it should be, since we need to clean up if no upgrade happened.
Moving the code into a goroutine makes the flow and invariants easier to understand.
There is one semantic change: Upgrade() does not return an error if the parent unexpectedly writes to the shutdown pipe. The likelihood of this happening is low, and it's not clear how severe that problem would be. By not rejecting upgrade requests we allow users to fix such problems without having to do a full restart.