diff --git a/docs/changes.txt b/docs/changes.txt index 6bf80b4f7e..d007a77cb2 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -649,6 +649,7 @@ wxMSW: - Fix handling of deleting directories in wxFileSystemWatcher (Eric Raijmakers). - Disable the use of new style wxDirDialog under Vista to work around a bug in its implementation under this system (jtrauntvein). +- Fix wxExecute() keeping open too many thread handles for too long (dannchr). wxOSX: 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