1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/corefoundation/utilsexec_cf.cpp 
   3 // Purpose:     Execution-related utilities for Darwin 
   4 // Author:      David Elliott, Ryan Norton (wxMacExecute) 
   5 // Modified by: Stefan Csomor (added necessary wxT for unicode builds) 
   8 // Copyright:   (c) David Elliott, Ryan Norton 
   9 // Licence:     wxWindows licence 
  10 // Notes:       This code comes from src/mac/carbon/utilsexc.cpp,1.11 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #include "wx/wxprec.h" 
  17 #endif //ndef WX_PRECOMP 
  18 #include "wx/unix/execute.h" 
  19 #include "wx/stdpaths.h" 
  20 #include "wx/apptrait.h" 
  24 #include <CoreFoundation/CFMachPort.h> 
  27 #include <mach/mach.h> 
  30 void wxMAC_MachPortEndProcessDetect(CFMachPortRef port
, void *data
) 
  32     wxEndProcessData 
*proc_data 
= (wxEndProcessData
*)data
; 
  33     wxLogDebug(wxT("Process ended")); 
  35     int rc 
= waitpid(abs(proc_data
->pid
), &status
, WNOHANG
); 
  38         wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!")); 
  41     if((rc 
!= -1) && WIFEXITED(status
)) 
  42         proc_data
->exitcode 
= WEXITSTATUS(status
); 
  44         proc_data
->exitcode 
= -1; 
  45     wxHandleProcessTermination(proc_data
); 
  48 int wxAddProcessCallbackForPid(wxEndProcessData 
*proc_data
, int pid
) 
  52     kern_return_t    kernResult
; 
  53     mach_port_t    taskOfOurProcess
; 
  54     mach_port_t    machPortForProcess
; 
  55     taskOfOurProcess 
= mach_task_self(); 
  56     if(taskOfOurProcess 
== MACH_PORT_NULL
) 
  58         wxLogDebug(wxT("No mach_task_self()")); 
  61     wxLogDebug(wxT("pid=%d"),pid
); 
  62     kernResult 
= task_for_pid(taskOfOurProcess
,pid
, &machPortForProcess
); 
  63     if(kernResult 
!= KERN_SUCCESS
) 
  65         wxLogDebug(wxT("no task_for_pid()")); 
  66         // try seeing if it is already dead or something 
  67         // FIXME: a better method would be to call the callback function 
  68         // from idle time until the process terminates. Of course, how 
  69         // likely is it that it will take more than 0.1 seconds for the 
  70         // mach terminate event to make its way to the BSD subsystem? 
  71         usleep(100); // sleep for 0.1 seconds 
  72         wxMAC_MachPortEndProcessDetect(NULL
, (void*)proc_data
); 
  75     CFMachPortContext termcb_contextinfo
; 
  76     termcb_contextinfo
.version 
= 0; 
  77     termcb_contextinfo
.info 
= (void*)proc_data
; 
  78     termcb_contextinfo
.retain 
= NULL
; 
  79     termcb_contextinfo
.release 
= NULL
; 
  80     termcb_contextinfo
.copyDescription 
= NULL
; 
  81     CFMachPortRef    CFMachPortForProcess
; 
  82     Boolean        ShouldFreePort
; 
  83     CFMachPortForProcess 
= CFMachPortCreateWithPort(NULL
, machPortForProcess
, NULL
, &termcb_contextinfo
, &ShouldFreePort
); 
  84     if(!CFMachPortForProcess
) 
  86         wxLogDebug(wxT("No CFMachPortForProcess")); 
  87         mach_port_deallocate(taskOfOurProcess
, machPortForProcess
); 
  92         kernResult 
= mach_port_deallocate(taskOfOurProcess
, machPortForProcess
); 
  93         if(kernResult
!=KERN_SUCCESS
) 
  95             wxLogDebug(wxT("Couldn't deallocate mach port")); 
  99     CFMachPortSetInvalidationCallBack(CFMachPortForProcess
, &wxMAC_MachPortEndProcessDetect
); 
 100     CFRunLoopSourceRef    runloopsource
; 
 101     runloopsource 
= CFMachPortCreateRunLoopSource(NULL
,CFMachPortForProcess
, (CFIndex
)0); 
 104         wxLogDebug(wxT("Couldn't create runloopsource")); 
 108     CFRelease(CFMachPortForProcess
); 
 110     CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource
,kCFRunLoopDefaultMode
); 
 111     CFRelease(runloopsource
); 
 112     wxLogDebug(wxT("Successfully added notification to the runloop")); 
 116 // NOTE: This doens't really belong here but this was a handy file to 
 117 // put it in because it's already compiled for wxCocoa and wxMac GUI lib. 
 118 static wxStandardPathsCF gs_stdPaths
; 
 119 wxStandardPathsBase
& wxGUIAppTraits::GetStandardPaths()