コード例 #1
0
void CFMessagePortInvalidate(CFMessagePortRef ms) {
    __CFGenericValidateType(ms, __kCFMessagePortTypeID);
    if (!__CFMessagePortIsDeallocing(ms)) {
	CFRetain(ms);
    }
    __CFMessagePortLock(ms);
    if (__CFMessagePortIsValid(ms)) {
	CFMessagePortInvalidationCallBack callout = ms->_icallout;
	CFRunLoopSourceRef source = ms->_source;
	CFMachPortRef replyPort = ms->_replyPort;
	CFMachPortRef port = ms->_port;
	CFStringRef name = ms->_name;
	void *info = NULL;

	__CFMessagePortUnsetValid(ms);
	if (!__CFMessagePortIsRemote(ms)) {
	    info = ms->_context.info;
	    ms->_context.info = NULL;
	}
	ms->_source = NULL;
	ms->_replyPort = NULL;
	__CFMessagePortUnlock(ms);

	__CFSpinLock(&__CFAllMessagePortsLock);
	if (NULL != (__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts)) {
	    CFDictionaryRemoveValue(__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts, name);
	}
	__CFSpinUnlock(&__CFAllMessagePortsLock);
	if (NULL != callout) {
	    callout(ms, info);
	}
	// We already know we're going invalid, don't need this callback
	// anymore; plus, this solves a reentrancy deadlock; also, this
	// must be done before the deallocate of the Mach port, to
	// avoid a race between the notification message which could be
	// handled in another thread, and this NULL'ing out.
	CFMachPortSetInvalidationCallBack(port, NULL);
	// For hashing and equality purposes, cannot get rid of _port here
	if (!__CFMessagePortIsRemote(ms) && NULL != ms->_context.release) {
	    ms->_context.release(info);
	}
	if (NULL != source) {
	    CFRunLoopSourceInvalidate(source);
	    CFRelease(source);
	}
	if (NULL != replyPort) {
	    CFMachPortInvalidate(replyPort);
	    CFRelease(replyPort);
	}
	if (__CFMessagePortIsRemote(ms)) {
	    // Get rid of our extra ref on the Mach port gotten from bs server
	    mach_port_deallocate(mach_task_self(), CFMachPortGetPort(port));
	}
    } else {
	__CFMessagePortUnlock(ms);
    }
    if (!__CFMessagePortIsDeallocing(ms)) {
	CFRelease(ms);
    }
}
コード例 #2
0
ファイル: IPC.c プロジェクト: aosm/Startup
void MonitorStartupItem (StartupContext aStartupContext, CFMutableDictionaryRef anItem)
{
    pid_t aPID = StartupItemGetPID(anItem);
    if (anItem && aPID > 0)
      {
        mach_port_t         aPort;
        kern_return_t       aResult;
        CFMachPortContext   aContext;
	CFMachPortRef       aMachPort;
	CFRunLoopSourceRef  aSource;
        TerminationContext  aTerminationContext = (TerminationContext) malloc(sizeof(struct TerminationContextStorage));
        
        aTerminationContext->aStartupContext = aStartupContext;
        aTerminationContext->anItem          = anItem;
        
        aContext.version = 0;
        aContext.info    = aTerminationContext;
        aContext.retain  = 0;
        aContext.release = 0;

        if ((aResult = task_for_pid(mach_task_self(), aPID, &aPort)) != KERN_SUCCESS)
		goto out_bad;

	if (!(aMachPort = CFMachPortCreateWithPort(NULL, aPort, NULL, &aContext, NULL)))
		goto out_bad;

	if (!(aSource = CFMachPortCreateRunLoopSource(NULL, aMachPort, 0))) {
		CFRelease(aMachPort);
		goto out_bad;
	}

	CFMachPortSetInvalidationCallBack(aMachPort, startupItemTerminated);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), aSource, kCFRunLoopCommonModes);
	CFRelease(aSource);
	CFRelease(aMachPort);
	return;
out_bad:
	/* The assumption is something failed, the task already terminated. */
	startupItemTerminated(NULL, aTerminationContext);
      }
}
コード例 #3
0
ファイル: CACFMachPort.cpp プロジェクト: 11020156/SampleCode
//	This constructor is the general form:
//	-	If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and
//		receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them
//		up.
//	-	If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort.
//		This is useful if you are only using the CFMachPort to track port death (aka invalidation).
//	-	If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation
//		callback on the CFMachPort.
CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData)
:
	mMachPort(NULL),
	mRunLoopSource(NULL),
	mOwnsPort(false)
{
	CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
	
	if(inMachPort == MACH_PORT_NULL)
	{
		mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
		ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort");
		mOwnsPort = true;
	}
	else
	{
		mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL);
		ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port");
		mOwnsPort = false;
	}

	mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
	if(mRunLoopSource == NULL)
	{
		if(mOwnsPort)
		{
			CFMachPortInvalidate(mMachPort);
		}
		CFRelease(mMachPort);
		mMachPort = NULL;
		DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource");
		throw CAException('what');
	}
	
	if(inInvalidationCallBack != NULL)
	{
		CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack);
	}
}
コード例 #4
0
CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) {
    CFMessagePortRef memory;
    CFMachPortRef native;
    CFMachPortContext ctx;
    uint8_t *utfname = NULL;
    CFIndex size;
    mach_port_t bp, port;
    kern_return_t ret;

    name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL);
    if (NULL == name) {
	return NULL;
    }
    __CFSpinLock(&__CFAllMessagePortsLock);
    if (NULL != name) {
	CFMessagePortRef existing;
	if (NULL != __CFAllRemoteMessagePorts && CFDictionaryGetValueIfPresent(__CFAllRemoteMessagePorts, name, (const void **)&existing)) {
	    __CFSpinUnlock(&__CFAllMessagePortsLock);
	    CFRelease(name);
	    CFAllocatorDeallocate(allocator, utfname);
	    return (CFMessagePortRef)CFRetain(existing);
	}
    }
    size = sizeof(struct __CFMessagePort) - sizeof(CFMessagePortContext) - sizeof(CFRuntimeBase);
    memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, __kCFMessagePortTypeID, size, NULL);
    if (NULL == memory) {
	__CFSpinUnlock(&__CFAllMessagePortsLock);
	if (NULL != name) {
	    CFRelease(name);
	}
	CFAllocatorDeallocate(allocator, utfname);
	return NULL;
    }
    __CFMessagePortUnsetValid(memory);
    __CFMessagePortSetRemote(memory);
    memory->_lock = 0;
    memory->_name = name;
    memory->_port = NULL;
    memory->_replies = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
    memory->_convCounter = 0;
    memory->_replyPort = NULL;
    memory->_source = NULL;
    memory->_icallout = NULL;
    memory->_callout = NULL;
    ctx.version = 0;
    ctx.info = memory;
    ctx.retain = NULL;
    ctx.release = NULL;
    ctx.copyDescription = NULL;
    task_get_bootstrap_port(mach_task_self(), &bp);
    ret = bootstrap_look_up(bp, utfname, &port);
    native = (KERN_SUCCESS == ret) ? CFMachPortCreateWithPort(allocator, port, __CFMessagePortDummyCallback, &ctx, NULL) : NULL;
    CFAllocatorDeallocate(allocator, utfname);
    if (NULL == native) {
	__CFSpinUnlock(&__CFAllMessagePortsLock);
	// name is released by deallocation
	CFRelease(memory);
	return NULL;
    }
    memory->_port = native;
    CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack);
    __CFMessagePortSetValid(memory);
    if (NULL != name) {
	if (NULL == __CFAllRemoteMessagePorts) {
	    __CFAllRemoteMessagePorts = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
	}
	CFDictionaryAddValue(__CFAllRemoteMessagePorts, name, memory);
    }
    __CFSpinUnlock(&__CFAllMessagePortsLock);
    return (CFMessagePortRef)memory;
}
コード例 #5
0
CFMessagePortRef CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo) {
    CFMessagePortRef memory;
    CFMachPortRef native;
    CFMachPortContext ctx;
    uint8_t *utfname = NULL;
    CFIndex size;

    if (shouldFreeInfo) *shouldFreeInfo = true;
    if (NULL != name) {
	name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL);
    }
    __CFSpinLock(&__CFAllMessagePortsLock);
    if (NULL != name) {
	CFMessagePortRef existing;
	if (NULL != __CFAllLocalMessagePorts && CFDictionaryGetValueIfPresent(__CFAllLocalMessagePorts, name, (const void **)&existing)) {
	    __CFSpinUnlock(&__CFAllMessagePortsLock);
	    CFRelease(name);
	    CFAllocatorDeallocate(allocator, utfname);
	    return (CFMessagePortRef)CFRetain(existing);
	}
    }
    size = sizeof(struct __CFMessagePort) - sizeof(CFRuntimeBase);
    memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, __kCFMessagePortTypeID, size, NULL);
    if (NULL == memory) {
	__CFSpinUnlock(&__CFAllMessagePortsLock);
	if (NULL != name) {
	    CFRelease(name);
	}
	CFAllocatorDeallocate(allocator, utfname);
	return NULL;
    }
    __CFMessagePortUnsetValid(memory);
    __CFMessagePortUnsetRemote(memory);
    memory->_lock = 0;
    memory->_name = name;
    memory->_port = NULL;
    memory->_replies = NULL;
    memory->_convCounter = 0;
    memory->_replyPort = NULL;
    memory->_source = NULL;
    memory->_icallout = NULL;
    memory->_callout = callout;
    memory->_context.info = NULL;
    memory->_context.retain = NULL;
    memory->_context.release = NULL;
    memory->_context.copyDescription = NULL;
    ctx.version = 0;
    ctx.info = memory;
    ctx.retain = NULL;
    ctx.release = NULL;
    ctx.copyDescription = NULL;
    native = CFMachPortCreate(allocator, __CFMessagePortDummyCallback, &ctx, NULL);
    if (NULL != native && NULL != name && !__CFMessagePortNativeSetNameLocal(native, utfname)) {
	CFMachPortInvalidate(native);
	CFRelease(native);
	native = NULL;
    }
    CFAllocatorDeallocate(allocator, utfname);
    if (NULL == native) {
	__CFSpinUnlock(&__CFAllMessagePortsLock);
	// name is released by deallocation
	CFRelease(memory);
	return NULL;
    }
    memory->_port = native;
    CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack);
    __CFMessagePortSetValid(memory);
    if (NULL != context) {
	memmove(&memory->_context, context, sizeof(CFMessagePortContext));
	memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
    }
    if (NULL != name) {
	if (NULL == __CFAllLocalMessagePorts) {
	    __CFAllLocalMessagePorts = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
	}
	CFDictionaryAddValue(__CFAllLocalMessagePorts, name, memory);
    }
    __CFSpinUnlock(&__CFAllMessagePortsLock);
    if (shouldFreeInfo) *shouldFreeInfo = false;
    return memory;
}
コード例 #6
0
ファイル: utilsexc_cf.cpp プロジェクト: Bluehorn/wxPython
int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid)
{
    if(pid < 1)
        return -1;
    kern_return_t    kernResult;
    mach_port_t    taskOfOurProcess;
    mach_port_t    machPortForProcess;
    taskOfOurProcess = mach_task_self();
    if(taskOfOurProcess == MACH_PORT_NULL)
    {
        wxLogDebug(wxT("No mach_task_self()"));
        return -1;
    }
    wxLogDebug(wxT("pid=%d"),pid);
    kernResult = task_for_pid(taskOfOurProcess,pid, &machPortForProcess);
    if(kernResult != KERN_SUCCESS)
    {
        wxLogDebug(wxT("no task_for_pid()"));
        // try seeing if it is already dead or something
        // FIXME: a better method would be to call the callback function
        // from idle time until the process terminates. Of course, how
        // likely is it that it will take more than 0.1 seconds for the
        // mach terminate event to make its way to the BSD subsystem?
        usleep(100); // sleep for 0.1 seconds
        wxMAC_MachPortEndProcessDetect(NULL, (void*)proc_data);
        return -1;
    }
    CFMachPortContext termcb_contextinfo;
    termcb_contextinfo.version = 0;
    termcb_contextinfo.info = (void*)proc_data;
    termcb_contextinfo.retain = NULL;
    termcb_contextinfo.release = NULL;
    termcb_contextinfo.copyDescription = NULL;
    CFMachPortRef    CFMachPortForProcess;
    Boolean        ShouldFreePort;
    CFMachPortForProcess = CFMachPortCreateWithPort(NULL, machPortForProcess, NULL, &termcb_contextinfo, &ShouldFreePort);
    if(!CFMachPortForProcess)
    {
        wxLogDebug(wxT("No CFMachPortForProcess"));
        mach_port_deallocate(taskOfOurProcess, machPortForProcess);
        return -1;
    }
    if(ShouldFreePort)
    {
        kernResult = mach_port_deallocate(taskOfOurProcess, machPortForProcess);
        if(kernResult!=KERN_SUCCESS)
        {
            wxLogDebug(wxT("Couldn't deallocate mach port"));
            return -1;
        }
    }
    CFMachPortSetInvalidationCallBack(CFMachPortForProcess, &wxMAC_MachPortEndProcessDetect);
    CFRunLoopSourceRef    runloopsource;
    runloopsource = CFMachPortCreateRunLoopSource(NULL,CFMachPortForProcess, (CFIndex)0);
    if(!runloopsource)
    {
        wxLogDebug(wxT("Couldn't create runloopsource"));
        return -1;
    }

    CFRelease(CFMachPortForProcess);

    CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource,kCFRunLoopDefaultMode);
    CFRelease(runloopsource);
    wxLogDebug(wxT("Successfully added notification to the runloop"));
    return 0;
}
コード例 #7
0
//
// Handle dead-port notifications.
// Since we don't actually run our own runloop here, we can't well use standard
// notifications to our own server port. So we use a CFMachPort facility instead.
//
void MachRunLoopServer::notifyIfDead(Port port, bool doNotify) const
{
	if (CFMachPortRef cfPort = CFMachPortCreateWithPort(NULL, port, NULL, NULL, NULL))
		CFMachPortSetInvalidationCallBack(cfPort, cfInvalidate);
}