From 110ffa16374c64e38f37ac73e486cea197783f33 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Wed, 7 Jun 2006 13:07:17 +0000 Subject: [PATCH] Alternative implementation for process termination detection on Intel, since task_for_pid doesn't work on Intel Macs. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39614 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/mac/corefoundation/utilsexc_cf.cpp | 100 +++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/mac/corefoundation/utilsexc_cf.cpp b/src/mac/corefoundation/utilsexc_cf.cpp index 12f26671c0..5eadfff570 100644 --- a/src/mac/corefoundation/utilsexc_cf.cpp +++ b/src/mac/corefoundation/utilsexc_cf.cpp @@ -18,8 +18,105 @@ #include "wx/unix/execute.h" #include "wx/stdpaths.h" #include "wx/apptrait.h" +#include "wx/thread.h" +#include "wx/process.h" +// Use polling instead of Mach ports, which doesn't work on Intel +// due to task_for_pid security issues. +// What's a better test for Intel vs PPC? +#ifdef WORDS_BIGENDIAN +#define USE_POLLING 0 +#else +#define USE_POLLING 1 +#endif + +#if USE_POLLING + +class wxProcessTerminationEventHandler: public wxEvtHandler +{ + public: + wxProcessTerminationEventHandler(wxEndProcessData* data) + { + m_data = data; + Connect(-1, wxEVT_END_PROCESS, wxProcessEventHandler(wxProcessTerminationEventHandler::OnTerminate)); + } + + void OnTerminate(wxProcessEvent& event) + { + Disconnect(-1, wxEVT_END_PROCESS, wxProcessEventHandler(wxProcessTerminationEventHandler::OnTerminate)); + wxHandleProcessTermination(m_data); + delete this; + } + + wxEndProcessData* m_data; +}; + +class wxProcessTerminationThread: public wxThread +{ + public: + wxProcessTerminationThread(wxEndProcessData* data, wxProcessTerminationEventHandler* handler): wxThread(wxTHREAD_DETACHED) + { + m_data = data; + m_handler = handler; + } + + virtual void* Entry(); + + wxProcessTerminationEventHandler* m_handler; + wxEndProcessData* m_data; +}; + +// The problem with this is that we may be examining the +// process e.g. in OnIdle at the point this cleans up the process, +// so we need to delay until it's safe. + +void* wxProcessTerminationThread::Entry() +{ + while (true) + { + usleep(100); + int status = 0; + int rc = waitpid(abs(m_data->pid), & status, WNOHANG); + if (rc != 0) + { + if ((rc != -1) && WIFEXITED(status)) + m_data->exitcode = WEXITSTATUS(status); + else + m_data->exitcode = -1; + + wxProcessEvent event; + wxPostEvent(m_handler, event); + + break; + } + } + + return NULL; +} + +int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid) +{ + if (pid < 1) + return -1; + + wxProcessTerminationEventHandler* handler = new wxProcessTerminationEventHandler(proc_data); + wxProcessTerminationThread* thread = new wxProcessTerminationThread(proc_data, handler); + + if (thread->Create() != wxTHREAD_NO_ERROR) + { + wxLogDebug(wxT("Could not create termination detection thread.")); + delete thread; + delete handler; + return -1; + } + + thread->Run(); + + return 0; +} + +#else #include #include @@ -113,6 +210,9 @@ int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid) return 0; } +#endif + // USE_POLLING + // NOTE: This doens't really belong here but this was a handy file to // put it in because it's already compiled for wxCocoa and wxMac GUI lib. static wxStandardPathsCF gs_stdPaths;