X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/62705a278a57b8d3dd67222f20b161584a86982d..ce7208d49d5ce2ca1dc0b3b83f14f1d04f29c4bf:/src/mac/corefoundation/utilsexc_cf.cpp?ds=inline diff --git a/src/mac/corefoundation/utilsexc_cf.cpp b/src/mac/corefoundation/utilsexc_cf.cpp index bb6e19d6ed..f9f5227660 100644 --- a/src/mac/corefoundation/utilsexc_cf.cpp +++ b/src/mac/corefoundation/utilsexc_cf.cpp @@ -18,119 +18,117 @@ #include "wx/unix/execute.h" #include "wx/stdpaths.h" #include "wx/apptrait.h" +#include "wx/thread.h" +#include "wx/process.h" -#ifdef __WXCOCOA__ -#include -#include +#include + +// 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 -#include "wx/mac/private.h" -#include "LaunchServices.h" +#define USE_POLLING 1 #endif -#include "wx/uri.h" -#include "wx/mac/corefoundation/cfstring.h" +#if USE_POLLING -long wxMacExecute(wxChar **argv, - int flags, - wxProcess *process) +#if wxUSE_THREADS +class wxProcessTerminationEventHandler: public wxEvtHandler { - CFIndex cfiCount = 0; - //get count - for(wxChar** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) + public: + wxProcessTerminationEventHandler(wxEndProcessData* data) { - ++cfiCount; + m_data = data; + Connect(-1, wxEVT_END_PROCESS, wxProcessEventHandler(wxProcessTerminationEventHandler::OnTerminate)); } - if(cfiCount == 0) //no file to launch? + void OnTerminate(wxProcessEvent& event) { - wxLogDebug(wxT("wxMacExecute No file to launch!")); - return -1; + Disconnect(-1, wxEVT_END_PROCESS, wxProcessEventHandler(wxProcessTerminationEventHandler::OnTerminate)); + wxHandleProcessTermination(m_data); + delete this; } - - CFURLRef cfurlApp = CFURLCreateWithString( - kCFAllocatorDefault, - wxMacCFStringHolder(*argv++, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlApp); - - CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); - if(!cfbApp) - { - wxLogDebug(wxT("wxMacExecute Bad bundle")); - CFRelease(cfurlApp); - return -1; - } - - - UInt32 dwBundleType, dwBundleCreator; - CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); - //Only call wxMacExecute for .app bundles - others could be actual unix programs - if(dwBundleType != 'APPL') + wxEndProcessData* m_data; +}; + +class wxProcessTerminationThread: public wxThread +{ + public: + wxProcessTerminationThread(wxEndProcessData* data, wxProcessTerminationEventHandler* handler): wxThread(wxTHREAD_DETACHED) { - CFRelease(cfurlApp); - return -1; + m_data = data; + m_handler = handler; } - - // - // We have a good bundle - so let's launch it! - // - - CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, cfiCount - 1, NULL); - - wxASSERT(cfaFiles); - - if(--cfiCount) + + 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) { - for( ; *argv != NULL ; ++argv) + usleep(100); + int status = 0; + int rc = waitpid(abs(m_data->pid), & status, WNOHANG); + if (rc != 0) { -// wxLogDebug(*argv); - wxString sCurrentFile; - - if(wxURI(*argv).IsReference()) - sCurrentFile = wxString(wxT("file://")) + *argv; + if ((rc != -1) && WIFEXITED(status)) + m_data->exitcode = WEXITSTATUS(status); else - sCurrentFile = *argv; - - CFURLRef cfurlCurrentFile = CFURLCreateWithString( - kCFAllocatorDefault, - wxMacCFStringHolder(sCurrentFile, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlCurrentFile); - - CFArrayAppendValue( - cfaFiles, - cfurlCurrentFile - ); + m_data->exitcode = -1; + + wxProcessEvent event; + wxPostEvent(m_handler, event); + + break; } } - - LSLaunchURLSpec launchspec; - launchspec.appURL = cfurlApp; - launchspec.itemURLs = cfaFiles; - launchspec.passThruParams = NULL; //AEDesc* - launchspec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; //TODO: Possibly be smarter with flags - launchspec.asyncRefCon = NULL; - - OSStatus status = LSOpenFromURLSpec(&launchspec, - NULL); //2nd is CFURLRef* really launched - - //cleanup - CFRelease(cfurlApp); - CFRelease(cfaFiles); - - //check for error - if(status != noErr) + + 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(wxString::Format(wxT("wxMacExecute ERROR: %d")), (int)status); + wxLogDebug(wxT("Could not create termination detection thread.")); + delete thread; + delete handler; return -1; } - return 0; //success + + thread->Run(); + + return 0; +} +#else // !wxUSE_THREADS +int wxAddProcessCallbackForPid(wxEndProcessData*, int) +{ + wxLogDebug(wxT("Could not create termination detection thread.")); + return -1; } +#endif // wxUSE_THREADS/!wxUSE_THREADS +#else // !USE_POLLING #include -#include extern "C" { #include } @@ -143,13 +141,13 @@ void wxMAC_MachPortEndProcessDetect(CFMachPortRef port, void *data) int rc = waitpid(abs(proc_data->pid), &status, WNOHANG); if(!rc) { - wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!")); - return; + wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!")); + return; } if((rc != -1) && WIFEXITED(status)) - proc_data->exitcode = WEXITSTATUS(status); + proc_data->exitcode = WEXITSTATUS(status); else - proc_data->exitcode = -1; + proc_data->exitcode = -1; wxHandleProcessTermination(proc_data); } @@ -212,7 +210,7 @@ int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid) wxLogDebug(wxT("Couldn't create runloopsource")); return -1; } - + CFRelease(CFMachPortForProcess); CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource,kCFRunLoopDefaultMode); @@ -221,11 +219,17 @@ int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid) return 0; } -// NOTE: This doens't really belong here but this was a handy file to +#endif // USE_POLLING/!USE_POLLING + +// NOTE: This doesn'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. +#if wxUSE_GUI + static wxStandardPathsCF gs_stdPaths; wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths() { return gs_stdPaths; } +#endif // wxUSE_GUI +