1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Execution-related utilities
4 // Author: Stefan Csomor
5 // Modified by: David Elliott
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 //#pragma implementation
19 #include "wx/unix/execute.h"
23 #include <mach/mach.h>
25 #include <CoreFoundation/CFMachPort.h>
33 #define wxEXECUTE_WIN_MESSAGE 10000
35 long wxExecute(const wxString
& command
, int flags
, wxProcess
*handler
)
38 wxFAIL_MSG( _T("wxExecute() not yet implemented") );
44 void wxMAC_MachPortEndProcessDetect(CFMachPortRef port
, void *data
)
46 wxEndProcessData
*proc_data
= (wxEndProcessData
*)data
;
47 wxLogDebug("Wow.. this actually worked!");
49 int rc
= waitpid(abs(proc_data
->pid
), &status
, WNOHANG
);
52 wxLogDebug("Mach port was invalidated, but process hasn't terminated!");
55 if((rc
!= -1) && WIFEXITED(status
))
56 proc_data
->exitcode
= WEXITSTATUS(status
);
58 proc_data
->exitcode
= -1;
59 wxHandleProcessTermination(proc_data
);
62 int wxAddProcessCallbackForPid(wxEndProcessData
*proc_data
, int pid
)
66 kern_return_t kernResult
;
67 mach_port_t taskOfOurProcess
;
68 mach_port_t machPortForProcess
;
69 taskOfOurProcess
= mach_task_self();
70 if(taskOfOurProcess
== MACH_PORT_NULL
)
72 wxLogDebug("No mach_task_self()");
75 wxLogDebug("pid=%d",pid
);
76 kernResult
= task_for_pid(taskOfOurProcess
,pid
, &machPortForProcess
);
77 if(kernResult
!= KERN_SUCCESS
)
79 wxLogDebug("no task_for_pid()");
80 // try seeing if it is already dead or something
81 // FIXME: a better method would be to call the callback function
82 // from idle time until the process terminates. Of course, how
83 // likely is it that it will take more than 0.1 seconds for the
84 // mach terminate event to make its way to the BSD subsystem?
85 usleep(100); // sleep for 0.1 seconds
86 wxMAC_MachPortEndProcessDetect(NULL
, (void*)proc_data
);
89 CFMachPortContext termcb_contextinfo
;
90 termcb_contextinfo
.version
= NULL
;
91 termcb_contextinfo
.info
= (void*)proc_data
;
92 termcb_contextinfo
.retain
= NULL
;
93 termcb_contextinfo
.release
= NULL
;
94 termcb_contextinfo
.copyDescription
= NULL
;
95 CFMachPortRef CFMachPortForProcess
;
96 Boolean ShouldFreePort
;
97 CFMachPortForProcess
= CFMachPortCreateWithPort(NULL
, machPortForProcess
, NULL
, &termcb_contextinfo
, &ShouldFreePort
);
98 if(!CFMachPortForProcess
)
100 wxLogDebug("No CFMachPortForProcess");
101 mach_port_deallocate(taskOfOurProcess
, machPortForProcess
);
106 kernResult
= mach_port_deallocate(taskOfOurProcess
, machPortForProcess
);
107 if(kernResult
!=KERN_SUCCESS
)
109 wxLogDebug("Couldn't deallocate mach port");
113 CFMachPortSetInvalidationCallBack(CFMachPortForProcess
, &wxMAC_MachPortEndProcessDetect
);
114 CFRunLoopSourceRef runloopsource
;
115 runloopsource
= CFMachPortCreateRunLoopSource(NULL
,CFMachPortForProcess
, (CFIndex
)0);
118 wxLogDebug("Couldn't create runloopsource");
122 CFRelease(CFMachPortForProcess
);
124 CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource
,kCFRunLoopDefaultMode
);
125 CFRelease(runloopsource
);
126 wxLogDebug("Successfully added notification to the runloop");