From d9a5f4a0bb6f683c3a2aada3a144ad7cdfac4bce Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 27 Mar 2014 00:02:16 +0000 Subject: [PATCH] Close monitoring thread handles as soon as possible in wxMSW. Don't leave the handles of all threads used for monitoring the child processes open until the main process termination, rather close them as soon as the monitored process terminates. This ensures that we don't accumulate potentially unbounded number of open handles if we keep launching new child processes. An even better idea would be to actually use a single thread for monitoring all of them, but this fix is much simpler and should fix the most acute problem for now. Closes #16123. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76200 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/utilsexc.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 82c7649972..8abb4609b1 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -121,6 +121,14 @@ static wxVector gs_asyncThreads; struct wxExecuteData { public: + wxExecuteData() + { + // The rest is initialized in the code creating the objects of this + // class, but the thread handle can't be set until later, so initialize + // it here to ensure we never use an uninitialized value in our dtor. + hThread = 0; + } + ~wxExecuteData() { if ( !::CloseHandle(hProcess) ) @@ -131,6 +139,7 @@ public: HWND hWnd; // window to send wxWM_PROC_TERMINATED to HANDLE hProcess; // handle of the process + HANDLE hThread; // handle of the thread monitoring its termination DWORD dwProcessId; // pid of the process wxProcess *handler; DWORD dwExitCode; // the exit code of the process @@ -361,6 +370,21 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message, else { // asynchronous execution - we should do the clean up + for ( wxVector::iterator it = gs_asyncThreads.begin(); + it != gs_asyncThreads.end(); + ++it ) + { + if ( *it == data->hThread ) + { + gs_asyncThreads.erase(it); + if ( !::CloseHandle(data->hThread) ) + { + wxLogLastError(wxT("CloseHandle(hThread)")); + } + break; + } + } + delete data; } @@ -978,6 +1002,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler, } gs_asyncThreads.push_back(hThread); + data->hThread = hThread; #if wxUSE_IPC && !defined(__WXWINCE__) // second part of DDE hack: now establish the DDE conversation with the