]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/corefoundation/utilsexc_cf.cpp
Removed the old, manual entry function, macro, and class category pages and replaced...
[wxWidgets.git] / src / mac / corefoundation / utilsexc_cf.cpp
index d32a8c8a5aaa5b1cf177ea151c42bbc1209f39b3..2d95454fe9e8e0c3b9cb8fd44a53c9e0902629e3 100644 (file)
 #endif //ndef WX_PRECOMP
 #include "wx/unix/execute.h"
 #include "wx/stdpaths.h"
+#include "wx/app.h"
 #include "wx/apptrait.h"
 #include "wx/thread.h"
 #include "wx/process.h"
 
 #include <sys/wait.h>
 
-// Use polling instead of Mach ports, which doesn't work on Intel
-// due to task_for_pid security issues.
-
-// http://developer.apple.com/technotes/tn/tn2050.html
-
-// 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
-
-#if wxUSE_THREADS
-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, 0);
-        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 // !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 <CoreFoundation/CFMachPort.h>
-extern "C" {
-#include <mach/mach.h>
-}
-
-void wxMAC_MachPortEndProcessDetect(CFMachPortRef port, void *data)
-{
-    wxEndProcessData *proc_data = (wxEndProcessData*)data;
-    wxLogDebug(wxT("Process ended"));
-    int status = 0;
-    int rc = waitpid(abs(proc_data->pid), &status, WNOHANG);
-    if(!rc)
-    {
-        wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!"));
-        return;
-    }
-    if((rc != -1) && WIFEXITED(status))
-        proc_data->exitcode = WEXITSTATUS(status);
-    else
-        proc_data->exitcode = -1;
-    wxHandleProcessTermination(proc_data);
-}
-
-int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid)
-{
-    if(pid < 1)
-        return -1;
-    kern_return_t    kernResult;
-    mach_port_t    taskOfOurProcess;
-    mach_port_t    machPortForProcess;
-    taskOfOurProcess = mach_task_self();
-    if(taskOfOurProcess == MACH_PORT_NULL)
-    {
-        wxLogDebug(wxT("No mach_task_self()"));
-        return -1;
-    }
-    wxLogDebug(wxT("pid=%d"),pid);
-    kernResult = task_for_pid(taskOfOurProcess,pid, &machPortForProcess);
-    if(kernResult != KERN_SUCCESS)
-    {
-        wxLogDebug(wxT("no task_for_pid()"));
-        // try seeing if it is already dead or something
-        // FIXME: a better method would be to call the callback function
-        // from idle time until the process terminates. Of course, how
-        // likely is it that it will take more than 0.1 seconds for the
-        // mach terminate event to make its way to the BSD subsystem?
-        usleep(100); // sleep for 0.1 seconds
-        wxMAC_MachPortEndProcessDetect(NULL, (void*)proc_data);
-        return -1;
-    }
-    CFMachPortContext termcb_contextinfo;
-    termcb_contextinfo.version = 0;
-    termcb_contextinfo.info = (void*)proc_data;
-    termcb_contextinfo.retain = NULL;
-    termcb_contextinfo.release = NULL;
-    termcb_contextinfo.copyDescription = NULL;
-    CFMachPortRef    CFMachPortForProcess;
-    Boolean        ShouldFreePort;
-    CFMachPortForProcess = CFMachPortCreateWithPort(NULL, machPortForProcess, NULL, &termcb_contextinfo, &ShouldFreePort);
-    if(!CFMachPortForProcess)
-    {
-        wxLogDebug(wxT("No CFMachPortForProcess"));
-        mach_port_deallocate(taskOfOurProcess, machPortForProcess);
-        return -1;
-    }
-    if(ShouldFreePort)
-    {
-        kernResult = mach_port_deallocate(taskOfOurProcess, machPortForProcess);
-        if(kernResult!=KERN_SUCCESS)
-        {
-            wxLogDebug(wxT("Couldn't deallocate mach port"));
-            return -1;
-        }
-    }
-    CFMachPortSetInvalidationCallBack(CFMachPortForProcess, &wxMAC_MachPortEndProcessDetect);
-    CFRunLoopSourceRef    runloopsource;
-    runloopsource = CFMachPortCreateRunLoopSource(NULL,CFMachPortForProcess, (CFIndex)0);
-    if(!runloopsource)
-    {
-        wxLogDebug(wxT("Couldn't create runloopsource"));
-        return -1;
-    }
-
-    CFRelease(CFMachPortForProcess);
-
-    CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource,kCFRunLoopDefaultMode);
-    CFRelease(runloopsource);
-    wxLogDebug(wxT("Successfully added notification to the runloop"));
-    return 0;
-}
-
-#endif // USE_POLLING/!USE_POLLING
-
-/////////////////////////////////////////////////////////////////////////////
-// New implementation avoiding mach ports entirely.
-
 #include <CoreFoundation/CFSocket.h>
 
 /*!
     Called due to source signal detected by the CFRunLoop.
     This is nearly identical to the wxGTK equivalent.
  */
-extern "C" void WXCF_EndProcessDetector(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, void const *data, void *info)
+extern "C" void WXCF_EndProcessDetector(CFSocketRef s,
+                                        CFSocketCallBackType WXUNUSED(callbackType),
+                                        CFDataRef WXUNUSED(address),
+                                        void const *WXUNUSED(data),
+                                        void *info)
 {
-    wxEndProcessData * const proc_data = static_cast<wxEndProcessData*>(info);
-
-/// This code could reasonably be shared between wxMac/wxCocoa and wxGTK ///
-    // PID is always positive on UNIX but wx uses the sign bit as a flag.
-    int pid = (proc_data->pid > 0) ? proc_data->pid : -proc_data->pid;
-    int status = 0;
-    int rc = waitpid(pid, &status, WNOHANG);
-    if(rc == 0)
-    {
-        // Keep waiting in case we got a spurious notification
-        // NOTE: In my limited testing, this doesn't happen.
-        return;
-    }
-
-    if(rc == -1)
-    {   // Error.. really shouldn't happen but try to gracefully handle it
-        wxLogLastError(_T("waitpid"));
-        proc_data->exitcode = -1;
-    }
-    else
-    {   // Process ended for some reason
-        wxASSERT_MSG(rc == pid, _T("unexpected waitpid() return value"));
-
-        if(WIFEXITED(status))
-            proc_data->exitcode = WEXITSTATUS(status);
-        else if(WIFSIGNALED(status))
-            // wxGTK doesn't do this but why not?
-            proc_data->exitcode = -WTERMSIG(status);
-        else
-        {   // Should NEVER happen according to waitpid docs
-            wxLogError(wxT("waitpid indicates process exited but not due to exiting or signalling"));
-            proc_data->exitcode = -1;
-        }
-    }
-/// The above code could reasonably be shared between wxMac/wxCocoa and wxGTK ///
-
     /*
-        Either waitpid failed or the process ended successfully.  Either way,
+        Either our pipe was closed or the process ended successfully.  Either way,
         we're done.  It's not if waitpid is going to magically succeed when
         we get fired again.  CFSocketInvalidate closes the fd for us and also
         invalidates the run loop source for us which should cause it to
@@ -285,18 +51,18 @@ extern "C" void WXCF_EndProcessDetector(CFSocketRef s, CFSocketCallBackType call
     CFSocketInvalidate(s);
 
     // Now tell wx that the process has ended.
-    wxHandleProcessTermination(proc_data);
+    wxHandleProcessTermination(static_cast<wxEndProcessData *>(info));
 }
 
 /*!
-    Implements the GUI-specific wxAddProcessCallback for both wxMac and
+    Implements the GUI-specific AddProcessCallback() for both wxMac and
     wxCocoa using the CFSocket/CFRunLoop API which is available to both.
     Takes advantage of the fact that sockets on UNIX are just regular
     file descriptors and thus even a non-socket file descriptor can
     apparently be used with CFSocket so long as you only tell CFSocket
     to do things with it that would be valid for a non-socket fd.
  */
-int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
+int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
 {
     static int s_last_tag = 0;
     CFSocketContext context =
@@ -309,13 +75,13 @@ int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
     CFSocketRef cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault,fd,kCFSocketReadCallBack,&WXCF_EndProcessDetector,&context);
     if(cfSocket == NULL)
     {
-        wxLogError("Failed to create socket for end process detection");
+        wxLogError(wxT("Failed to create socket for end process detection"));
         return 0;
     }
     CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, /*highest priority:*/0);
     if(runLoopSource == NULL)
     {
-        wxLogError("Failed to create CFRunLoopSource from CFSocket for end process detection");
+        wxLogError(wxT("Failed to create CFRunLoopSource from CFSocket for end process detection"));
         // closes the fd.. we can't really stop it, nor do we necessarily want to.
         CFSocketInvalidate(cfSocket);
         CFRelease(cfSocket);
@@ -342,8 +108,6 @@ int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
 
 // 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
-
 #if wxUSE_STDPATHS
 static wxStandardPathsCF gs_stdPaths;
 wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths()
@@ -352,5 +116,3 @@ wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths()
 }
 #endif
 
-#endif // wxUSE_GUI
-