There was a possible deadlock in the particular case in which the server is
attempting to process a shutdown request (from the client) at the time that
shutdown is called manually on the server struct. Because shutdowns were
executed synchronously, the shutdown request could not complete because it
could not acquire the lock to shutdown the server. But then the manual shutdown
(which acquired the lock first) could not complete because the shutdown request
was unfinished.
This is solved by executing the shutdown asynchronously when it is requested,
so that the shutdown request can complete and deadlock is avoided.
Includes a test that reproduces the issue (before the changes to server.go).
There was a possible deadlock in the particular case in which the server is attempting to process a shutdown request (from the client) at the time that shutdown is called manually on the server struct. Because shutdowns were executed synchronously, the shutdown request could not complete because it could not acquire the lock to shutdown the server. But then the manual shutdown (which acquired the lock first) could not complete because the shutdown request was unfinished.
This is solved by executing the shutdown asynchronously when it is requested, so that the shutdown request can complete and deadlock is avoided.
Includes a test that reproduces the issue (before the changes to server.go).