In the previois implementation, async_close() was allowed to invoke
handle_close() in place. async_close() is always called under a
mutex. handle_close() acquires the mutex too, resulting in a deadlock.
The problem didn't appear in practice because the circumstances when
handle_close() is called in place are very rare: uv_udp_init() should
fail to make it happen, or double async_close() call should happen.
In the new implementation, instead of calling handle_close() in place,
async_close() returns false instead, which means that there is no need
to wait for handle_close() call.
In the previois implementation, async_close() was allowed to invoke handle_close() in place. async_close() is always called under a mutex. handle_close() acquires the mutex too, resulting in a deadlock.
The problem didn't appear in practice because the circumstances when handle_close() is called in place are very rare: uv_udp_init() should fail to make it happen, or double async_close() call should happen.
In the new implementation, instead of calling handle_close() in place, async_close() returns false instead, which means that there is no need to wait for handle_close() call.