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
This commit is contained in:
@@ -121,6 +121,14 @@ static wxVector<HANDLE> gs_asyncThreads;
|
|||||||
struct wxExecuteData
|
struct wxExecuteData
|
||||||
{
|
{
|
||||||
public:
|
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()
|
~wxExecuteData()
|
||||||
{
|
{
|
||||||
if ( !::CloseHandle(hProcess) )
|
if ( !::CloseHandle(hProcess) )
|
||||||
@@ -131,6 +139,7 @@ public:
|
|||||||
|
|
||||||
HWND hWnd; // window to send wxWM_PROC_TERMINATED to
|
HWND hWnd; // window to send wxWM_PROC_TERMINATED to
|
||||||
HANDLE hProcess; // handle of the process
|
HANDLE hProcess; // handle of the process
|
||||||
|
HANDLE hThread; // handle of the thread monitoring its termination
|
||||||
DWORD dwProcessId; // pid of the process
|
DWORD dwProcessId; // pid of the process
|
||||||
wxProcess *handler;
|
wxProcess *handler;
|
||||||
DWORD dwExitCode; // the exit code of the process
|
DWORD dwExitCode; // the exit code of the process
|
||||||
@@ -361,6 +370,21 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// asynchronous execution - we should do the clean up
|
// asynchronous execution - we should do the clean up
|
||||||
|
for ( wxVector<HANDLE>::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;
|
delete data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,6 +1002,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gs_asyncThreads.push_back(hThread);
|
gs_asyncThreads.push_back(hThread);
|
||||||
|
data->hThread = hThread;
|
||||||
|
|
||||||
#if wxUSE_IPC && !defined(__WXWINCE__)
|
#if wxUSE_IPC && !defined(__WXWINCE__)
|
||||||
// second part of DDE hack: now establish the DDE conversation with the
|
// second part of DDE hack: now establish the DDE conversation with the
|
||||||
|
Reference in New Issue
Block a user