Fix wxExecute process end detect behavior for wxCocoa and wxMac. I have no
idea why the current code used for Intel Macs doesn't work but it's not working for me at all. This should probably be backported to 2.8. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49155 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -223,6 +223,123 @@ int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid)
|
||||
|
||||
#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)
|
||||
{
|
||||
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,
|
||||
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
|
||||
release the CFSocket (thus causing it to be deallocated) and remove
|
||||
itself from the runloop which should release it and cause it to also
|
||||
be deallocated. Of course, it's possible the RunLoop hangs onto
|
||||
one or both of them by retaining/releasing them within its stack
|
||||
frame. However, that shouldn't be depended on. Assume that s is
|
||||
deallocated due to the following call.
|
||||
*/
|
||||
CFSocketInvalidate(s);
|
||||
|
||||
// Now tell wx that the process has ended.
|
||||
wxHandleProcessTermination(proc_data);
|
||||
}
|
||||
|
||||
/*!
|
||||
Implements the GUI-specific wxAddProcessCallback 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)
|
||||
{
|
||||
static int s_last_tag = 0;
|
||||
CFSocketContext context =
|
||||
{ 0
|
||||
, static_cast<void*>(proc_data)
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
};
|
||||
CFSocketRef cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault,fd,kCFSocketReadCallBack,&WXCF_EndProcessDetector,&context);
|
||||
if(cfSocket == NULL)
|
||||
{
|
||||
wxLogError("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");
|
||||
// closes the fd.. we can't really stop it, nor do we necessarily want to.
|
||||
CFSocketInvalidate(cfSocket);
|
||||
CFRelease(cfSocket);
|
||||
return 0;
|
||||
}
|
||||
// Now that the run loop source has the socket retained and we no longer
|
||||
// need to refer to it within this method, we can release it.
|
||||
CFRelease(cfSocket);
|
||||
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
|
||||
// Now that the run loop has the source retained we can release it.
|
||||
CFRelease(runLoopSource);
|
||||
|
||||
/*
|
||||
Feed wx some bullshit.. we don't use it since CFSocket helpfully passes
|
||||
itself into our callback and that's enough to be able to
|
||||
CFSocketInvalidate it which is all we need to do to get everything we
|
||||
just created to be deallocated.
|
||||
*/
|
||||
return ++s_last_tag;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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
|
||||
|
@@ -1227,7 +1227,16 @@ bool wxHandleFatalExceptions(bool doit)
|
||||
// wxExecute support
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define USE_OLD_DARWIN_END_PROCESS_DETECT (defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__)))
|
||||
/*
|
||||
NOTE: If this proves not to work well for wxMac then move back to the old
|
||||
behavior. If, however, it proves to work just fine, nuke all of the code
|
||||
for the old behavior. I strongly suggest backporting this to 2.8 as well.
|
||||
However, beware that while you can nuke the old code here, you cannot
|
||||
nuke the wxAddProcessCallbackForPid from the 2.8 branch (found in
|
||||
utilsexc_cf since it's an exported symbol).
|
||||
*/
|
||||
// #define USE_OLD_DARWIN_END_PROCESS_DETECT (defined(__DARWIN__) && defined(__WXMAC__))
|
||||
#define USE_OLD_DARWIN_END_PROCESS_DETECT 0
|
||||
|
||||
// wxMac/wxCocoa don't use the same process end detection mechanisms so we don't
|
||||
// need wxExecute-related helpers for them
|
||||
|
Reference in New Issue
Block a user