Files
wxWidgets/src/osx/core/utilsexc_cf.cpp
Vadim Zeitlin 7a03aa0188 Back port of wxSocket-related fixes from trunk.
This patch combines the changes from the following trunk revisions:
 - r61675
 - r61676
 - r61677
 - r61678
 - r61685
 - r61686
 - r61687
 - r61688
 - r61689
 - r61690
 - r61696
 - r61726

It refactors wxSocketImpl creation to use a Mac-specific version of it in GUI
Mac applications which fixes generation of socket events under Mac (see #11030)
and also fixes bug in wxSocketServer::WaitForAccept() (see #11107).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_9_0_BRANCH@61734 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2009-08-22 17:40:08 +00:00

135 lines
5.2 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/osx/corefoundation/utilsexec_cf.cpp
// Purpose: Execution-related utilities for Darwin
// Author: David Elliott, Ryan Norton (wxMacExecute)
// Modified by: Stefan Csomor (added necessary wxT for unicode builds)
// Created: 2004-11-04
// RCS-ID: $Id$
// Copyright: (c) David Elliott, Ryan Norton
// Licence: wxWindows licence
// Notes: This code comes from src/osx/carbon/utilsexc.cpp,1.11
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/utils.h"
#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>
#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 WXUNUSED(callbackType),
CFDataRef WXUNUSED(address),
void const *WXUNUSED(data),
void *info)
{
/*
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
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(static_cast<wxEndProcessData *>(info));
}
/*!
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 wxGUIAppTraits::AddProcessCallback(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(wxT("Failed to create socket for end process detection"));
return 0;
}
CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, /*highest priority:*/0);
if(runLoopSource == NULL)
{
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);
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_STDPATHS
static wxStandardPathsCF gs_stdPaths;
wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths()
{
return gs_stdPaths;
}
#endif
#if wxUSE_SOCKETS
// we need to implement this method in a file of the core library as it should
// only be used for the GUI applications but we can't use socket stuff from it
// directly as this would create unwanted dependencies of core on net library
//
// so we have this global pointer which is set from sockosx.cpp when it is
// linked in and we simply return it from here
extern WXDLLIMPEXP_BASE wxSocketManager *wxOSXSocketManagerCF;
wxSocketManager *wxGUIAppTraits::GetSocketManager()
{
return wxOSXSocketManagerCF ? wxOSXSocketManagerCF
: wxGUIAppTraitsBase::GetSocketManager();
}
#endif // wxUSE_SOCKETS