NetKDRequestDevice: Fix use-after-free crash
Explicitly shut down work queues in NetKDRequestDevice's destructor to prevent their threads from accessing members after they've been freed. This crash would occur sporadically if NetKDRequestDevice's periodic download or mail checks happened to overlap with emulation shutdown in the wrong way. An example sequence of events that could cause the crash: * m_scheduler_timer_thread queues a periodic Download event in m_scheduler_work_queue, then waits for m_shutdown_event. * A request to stop emulation results in s_ios being reset by the CPU thread. This triggers NetKDRequestDevice's destructor which sets m_shutdown_event and joins m_scheduler_timer_thread. * m_scheduler_timer_thread wakes from m_shutdown_event and returns from its thread function, ending the thread. * The CPU thread resumes execution at the end of NetKDRequestDevice's destructor and begins destroying NetKDRequestDevice's members in reverse declaration order. * m_http is declared after m_scheduler_work_queue and is therefore destroyed earlier. * m_scheduler_work_queue's destructor calls its Shutdown function, which by default finishes the work items in the queue. * The queued Download event calls KDDownload which calls m_http.Get() which calls Fetch() which passes garbage data from the freed m_curl into curl_easy_setopt(). * Curl promptly crashes. Shutting down the work queues manually in the destructor prevents the above because m_http and the other members don't get freed until after the queue threads finish.
This commit is contained in:
parent
57327be7f3
commit
dd1f5f9726
|
@ -190,6 +190,8 @@ NetKDRequestDevice::~NetKDRequestDevice()
|
|||
}
|
||||
|
||||
m_scheduler_timer_thread.join();
|
||||
m_scheduler_work_queue.Shutdown();
|
||||
m_work_queue.Shutdown();
|
||||
}
|
||||
|
||||
void NetKDRequestDevice::Update()
|
||||
|
|
Loading…
Reference in New Issue