Skip to content

Commit 9987317

Browse files
bholmesUnityAlex
authored andcommitted
Fix debugger thread shutdown hang.
The previous fix from the <= 2021.2 version of Unity/Mono was to call mono_threads_suspend_abort_syscall inside transport_close1. mono_threads_suspend_abort_syscall interrupts the debugger thread and and forces the debugger thread to cancel pending IO (CancelIo.) mono_threads_suspend_abort_syscall does not block. This causes a race condition if the closesocket call in transport_close1 executes before CancelIo can be called on the debugger thread. This fix moves the call to mono_threads_suspend_abort_syscall stop_debugger_thread where we can use the existing wait code to ensure we have cancelled the IO call. fixes case 1374958 Previous fix: #574 fix formatting
1 parent 7084c05 commit 9987317

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

mono/mini/debugger-agent.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,9 +1456,6 @@ socket_transport_close1 (void)
14561456
/* Close the read part only so it can still send back replies */
14571457
/* Also shut down the connection listener so that we can exit normally */
14581458
#ifdef HOST_WIN32
1459-
MonoThreadInfo* info = mono_thread_info_lookup(debugger_thread_id);
1460-
if (info)
1461-
mono_threads_suspend_abort_syscall(info);
14621459
/* SD_RECEIVE doesn't break the recv in the debugger thread */
14631460
shutdown (conn_fd, SD_BOTH);
14641461
shutdown (listen_fd, SD_BOTH);
@@ -1680,14 +1677,9 @@ transport_handshake (void)
16801677
}
16811678

16821679
static void
1683-
stop_debugger_thread (void)
1680+
wait_for_debugger_thread_to_stop ()
16841681
{
1685-
if (!agent_inited)
1686-
return;
1687-
1688-
transport_close1 ();
1689-
1690-
/*
1682+
/*
16911683
* Wait for the thread to exit.
16921684
*
16931685
* If we continue with the shutdown without waiting for it, then the client might
@@ -1704,6 +1696,36 @@ stop_debugger_thread (void)
17041696
if (debugger_thread_handle)
17051697
mono_thread_info_wait_one_handle (debugger_thread_handle, MONO_INFINITE_WAIT, TRUE);
17061698
}
1699+
}
1700+
1701+
static void
1702+
stop_debugger_thread (void)
1703+
{
1704+
if (!agent_inited)
1705+
return;
1706+
1707+
#ifdef HOST_WIN32
1708+
gboolean debuggerAttached = mono_is_debugger_attached ();
1709+
1710+
// We need to make the call to mono_threads_suspend_abort_syscall to break any
1711+
// hung accept calls on windows.
1712+
MonoThreadInfo* info = mono_thread_info_lookup (debugger_thread_id);
1713+
if (info) {
1714+
mono_threads_suspend_abort_syscall (info);
1715+
1716+
// On Windows we must wait for the debugger to stop before
1717+
// closing the transport. !debuggerAttached means we are not in
1718+
// socket accept, the problematic blocking call.
1719+
if (!debuggerAttached)
1720+
{
1721+
wait_for_debugger_thread_to_stop ();
1722+
}
1723+
}
1724+
1725+
#endif
1726+
transport_close1 ();
1727+
1728+
wait_for_debugger_thread_to_stop ();
17071729

17081730
transport_close2 ();
17091731
}

0 commit comments

Comments
 (0)