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()