static void __CFMessagePortDeallocate(CFTypeRef cf) {
    CFMessagePortRef ms = (CFMessagePortRef)cf;
    __CFMessagePortSetIsDeallocing(ms);
    CFMessagePortInvalidate(ms);
    // Delay cleanup of _replies until here so that invalidation during
    // SendRequest does not cause _replies to disappear out from under that function.
    if (NULL != ms->_replies) {
	CFRelease(ms->_replies);
    }
    if (NULL != ms->_name) {
	CFRelease(ms->_name);
    }
    if (NULL != ms->_port) {
	if (__CFMessagePortExtraMachRef(ms)) {
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_SEND, -1);
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_RECEIVE, -1);
	}
	CFMachPortInvalidate(ms->_port);
	CFRelease(ms->_port);
    }

    // A remote message port for a local message port in the same process will get the
    // same mach port, and the remote port will keep the mach port from being torn down,
    // thus keeping the remote port from getting any sort of death notification and
    // auto-invalidating; so we manually implement the 'auto-invalidation' here by
    // tickling each remote port to check its state after any message port is destroyed,
    // but most importantly after local message ports are destroyed.
    __CFLock(&__CFAllMessagePortsLock);
    CFMessagePortRef *remotePorts = NULL;
    CFIndex cnt = 0;
    if (NULL != __CFAllRemoteMessagePorts) {
	cnt = CFDictionaryGetCount(__CFAllRemoteMessagePorts);
	remotePorts = CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFMessagePortRef), __kCFAllocatorGCScannedMemory);
	CFDictionaryGetKeysAndValues(__CFAllRemoteMessagePorts, NULL, (const void **)remotePorts);
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    CFRetain(remotePorts[idx]);
	}
    }
    __CFUnlock(&__CFAllMessagePortsLock);
    if (remotePorts) {
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    // as a side-effect, this will auto-invalidate the CFMessagePort if the CFMachPort is invalid
	    CFMessagePortIsValid(remotePorts[idx]);
	    CFRelease(remotePorts[idx]);
	}
	CFAllocatorDeallocate(kCFAllocatorSystemDefault, remotePorts);
    }
}
示例#2
0
static Boolean __CFMessagePortNativeSetNameLocal(CFMachPortRef port, uint8_t *portname) {
    mach_port_t bp;
    kern_return_t ret;
    task_get_bootstrap_port(mach_task_self(), &bp);
    ret = bootstrap_register(bp, portname, CFMachPortGetPort(port));
    return (ret == KERN_SUCCESS) ? true : false;
}
示例#3
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);
    }
}
示例#4
0
文件: IPC.c 项目: aosm/Startup
CFRunLoopSourceRef CreateIPCRunLoopSource(CFStringRef aPortName, StartupContext aStartupContext)
{
    CFRunLoopSourceRef	aSource = NULL;
    CFMachPortRef	aMachPort = NULL;
    CFMachPortContext	aContext;
    kern_return_t       aKernReturn = KERN_FAILURE;

    aContext.version = 0;
    aContext.info = (void*) aStartupContext;
    aContext.retain = 0;
    aContext.release = 0;
    aContext.copyDescription = 0;
    aMachPort = CFMachPortCreate(NULL, NULL, &aContext, NULL);
    
    if (aMachPort && aPortName)
      {
        CFIndex aPortNameLength = CFStringGetLength(aPortName);
        CFIndex aPortNameSize = CFStringGetMaximumSizeForEncoding(aPortNameLength, kCFStringEncodingUTF8) + 1;
        uint8_t *aBuffer = CFAllocatorAllocate(NULL, aPortNameSize, 0);
        if (aBuffer && CFStringGetCString(aPortName,
                                        aBuffer,
                                        aPortNameSize,
                                        kCFStringEncodingUTF8))
          {
            mach_port_t   aBootstrapPort;
            task_get_bootstrap_port(mach_task_self(), &aBootstrapPort);
            aKernReturn = bootstrap_register(aBootstrapPort, aBuffer, CFMachPortGetPort(aMachPort));
          }
        if (aBuffer) CFAllocatorDeallocate(NULL, aBuffer);
      }

    if (aMachPort && aKernReturn == KERN_SUCCESS)
      {
        CFRunLoopSourceContext1 aSourceContext;
        aSourceContext.version = 1;
        aSourceContext.info = aMachPort;
        aSourceContext.retain = CFRetain;
        aSourceContext.release = CFRelease;
        aSourceContext.copyDescription = CFCopyDescription;
        aSourceContext.equal = CFEqual;
        aSourceContext.hash = CFHash;
        aSourceContext.getPort = getIPCPort;
        aSourceContext.perform = (void*)handleIPCMessage;
        aSource = CFRunLoopSourceCreate(NULL, 0, (CFRunLoopSourceContext*)&aSourceContext);
      }

    if (aMachPort && (!aSource || aKernReturn != KERN_SUCCESS))
      {
        CFMachPortInvalidate(aMachPort);
        CFRelease(aMachPort);
        aMachPort = NULL;
      }
    return aSource;
}
示例#5
0
void
_SCDPluginExecInit()
{
	struct sigaction	act;
	CFMachPortContext	context	= { 0
					  , (void *)1
					  , NULL
					  , NULL
					  , childReapedMPCopyDescription
					  };

	CFRunLoopSourceRef	rls;

	// create the "a child has been reaped" notification port
	childReaped = CFMachPortCreate(NULL, childrenReaped, &context, NULL);

	// set queue limit
	{
		mach_port_limits_t	limits;
		kern_return_t		status;

		limits.mpl_qlimit = 1;
		status = mach_port_set_attributes(mach_task_self(),
						  CFMachPortGetPort(childReaped),
						  MACH_PORT_LIMITS_INFO,
						  (mach_port_info_t)&limits,
						  MACH_PORT_LIMITS_INFO_COUNT);
		if (status != KERN_SUCCESS) {
			perror("mach_port_set_attributes");
		}
	}

	// add to our runloop
	rls = CFMachPortCreateRunLoopSource(NULL, childReaped, 0);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
	CFRelease(rls);

	// enable signal handler
	act.sa_handler = reaper;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_RESTART|SA_NOCLDSTOP;
	if (sigaction(SIGCHLD, &act, NULL) == -1) {
		perror("sigaction");
	}

	return;
}
示例#6
0
static void
reaper(int sigraised)
{
	/*
	 * block additional SIGCHLD's until current children have
	 * been reaped.
	 */
	blockSignal();

	/*
	 * send message to indicate that at least one child is ready
	 * to be reaped.
	 */
	_SC_sendMachMessage(CFMachPortGetPort(childReaped), 0);

	return;
}
示例#7
0
/* Radar 6386278 New launchd api is npot on embedded yet */
int
ppp_mach_start_server()
{
    boolean_t		active;
    kern_return_t 	status;
    CFRunLoopSourceRef	rls;
	
	active = FALSE;
	status = bootstrap_status(bootstrap_port, PPPCONTROLLER_SERVER, &active);
	
	switch (status) {
		case BOOTSTRAP_SUCCESS:
			if (active) {
				fprintf(stderr, "\"%s\" is currently active.\n", 
						PPPCONTROLLER_SERVER);
				return -1;
			}
			break;
		case BOOTSTRAP_UNKNOWN_SERVICE:
			break;
		default:
			fprintf(stderr,
					"bootstrap_status(): %s\n", mach_error_string(status));
			return -1;
    }
	
    gServer_cfport = CFMachPortCreate(NULL, server_handle_request, NULL, NULL);
    rls = CFMachPortCreateRunLoopSource(NULL, gServer_cfport, 0);
	gControllerRunloop = CFRunLoopGetCurrent();
    CFRunLoopAddSource(gControllerRunloop, rls, kCFRunLoopDefaultMode);
	CFRunLoopAddSource(gControllerRunloop, gTerminalrls, kCFRunLoopDefaultMode);	
    CFRelease(rls);
	
    status = bootstrap_register(bootstrap_port, PPPCONTROLLER_SERVER, 
								CFMachPortGetPort(gServer_cfport));
    if (status != BOOTSTRAP_SUCCESS) {
		mach_error("bootstrap_register", status);
		return -1;
    }
	
    return 0;
}
static
void init_self_audittoken(void)
{
    /* create a mach port and an event source */
    CFMachPortRef server_port = CFMachPortCreate (NULL, server_callback, NULL, false);
    CFRunLoopSourceRef server_source = CFMachPortCreateRunLoopSource(NULL, server_port, 0/*order*/);

    /* add the source to the current run loop */
    CFRunLoopAddSource(CFRunLoopGetCurrent(), server_source, kCFRunLoopDefaultMode);
    CFRelease(server_source);

    /* Send the request */
    sectask_client_request(CFMachPortGetPort(server_port));

    /* Run the loop to process the message */
    CFRunLoopRun();

    /* done */
    CFRelease(server_port);

}
示例#9
0
__private_extern__
int
server_shutdown()
{
	if (configd_port != NULL) {
		mach_port_t	service_port	= CFMachPortGetPort(configd_port);

		CFMachPortInvalidate(configd_port);
		CFRelease(configd_port);
		configd_port = NULL;

		if (service_port != MACH_PORT_NULL) {
			(void) mach_port_mod_refs(mach_task_self(),
						  service_port,
						  MACH_PORT_RIGHT_RECEIVE,
						  -1);
		}
	}

	return EX_OK;
}
示例#10
0
static void __DACommandSignal( int sig )
{
    /*
     * Process a SIGCHLD signal.  mach_msg() is safe from a signal handler.
     */

    mach_msg_header_t message;
    kern_return_t     status;

    message.msgh_bits        = MACH_MSGH_BITS( MACH_MSG_TYPE_COPY_SEND, 0 );
    message.msgh_id          = 0;
    message.msgh_local_port  = MACH_PORT_NULL;
    message.msgh_remote_port = CFMachPortGetPort( __gDACommandRunLoopSourcePort );
    message.msgh_reserved    = 0;
    message.msgh_size        = sizeof( message );

    status = mach_msg( &message, MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL );

    if ( status == MACH_SEND_TIMED_OUT )
    {
        mach_msg_destroy( &message );
    }
}
示例#11
0
kern_return_t	CACFMachPort::ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut)
{
	//	snag the port
	mach_port_t thePort = CFMachPortGetPort(mMachPort);

	//	fill out the message header
	outMessage->msgh_bits = 0;
	outMessage->msgh_size = 0;
	outMessage->msgh_remote_port = MACH_PORT_NULL;
	outMessage->msgh_local_port = thePort;
	outMessage->msgh_reserved = 0;
	outMessage->msgh_id = 0;

	//	figure the options
	mach_msg_options_t theOptions = MACH_RCV_MSG;
	if(inTimeOut > 0)
	{
		theOptions |= MACH_RCV_TIMEOUT;
	}
	
	//	receive the messsage
	return mach_msg(outMessage, theOptions, 0, inMaxMessageSize, thePort, inTimeOut, MACH_PORT_NULL);
}
/*! Opens a connection to the iSCSI initiator.  A connection must be
 *  successfully opened before any of the supporting functions below can be
 *  called. */
errno_t iSCSIKernelInitialize(iSCSIKernelNotificationCallback callback)
{
    kern_return_t result;
     	
	// Create a dictionary to match iSCSIkext
	CFMutableDictionaryRef matchingDict = NULL;
	matchingDict = IOServiceMatching(kiSCSIVirtualHBA_IOClassName);
    
    service = IOServiceGetMatchingService(kIOMasterPortDefault,matchingDict);
    
	// Check to see if the driver was found in the I/O registry
	if(service == IO_OBJECT_NULL)
		return kIOReturnNotFound;
    
	// Using the service handle, open a connection
    result = IOServiceOpen(service,mach_task_self(),0,&connection);
	
	if(result != kIOReturnSuccess) {
        IOObjectRelease(service);
        return kIOReturnNotFound;
    }
    
    notificationContext.info = (void *)&notificationContext;
    notificationContext.version = 0;
    notificationContext.release = NULL;
    notificationContext.retain  = NULL;
    notificationContext.copyDescription = NULL;
    
    // Create a mach port to receive notifications from the kernel
    notificationPort = CFMachPortCreate(kCFAllocatorDefault,
                                        iSCSIKernelNotificationHandler,
                                        &notificationContext,NULL);
    IOConnectSetNotificationPort(connection,0,CFMachPortGetPort(notificationPort),0);
    

    return IOReturnToErrno(IOConnectCallScalarMethod(connection,kiSCSIOpenInitiator,0,0,0,0));
}
示例#13
0
文件: IPC.c 项目: aosm/Startup
/**
 * A CFMachPort invalidation callback that records the termination of
 * a startup item task.  Stops the current run loop to give system_starter
 * another go at running items.
 **/
static void startupItemTerminated (CFMachPortRef aMachPort, void *anInfo)
{
    TerminationContext aTerminationContext = (TerminationContext) anInfo;
    
    if (aMachPort)
      {
        mach_port_deallocate(mach_task_self(), CFMachPortGetPort(aMachPort));
      }
    
    if (aTerminationContext && aTerminationContext->anItem)
      {
        pid_t	 		aPID 		= 0;
        pid_t	 		rPID 		= 0;
        int			aStatus		= 0;
        CFMutableDictionaryRef	anItem          = aTerminationContext->anItem;
        StartupContext		aStartupContext = aTerminationContext->aStartupContext;

        /* Get the exit status */
        if (anItem)
          {
            aPID = StartupItemGetPID(anItem);
            if (aPID > 0)
                rPID = waitpid(aPID, &aStatus, WNOHANG);
          }
          
        if (aStartupContext)
          {
            --aStartupContext->aRunningCount;

            /* Record the item's status */
            if (aStartupContext->aStatusDict)
              {
                StartupItemExit(aStartupContext->aStatusDict, anItem, (WIFEXITED(aStatus) && WEXITSTATUS(aStatus) == 0));
                if (aStatus)
                  {
                    warning(CFSTR("%@ (%d) did not complete successfully.\n"), CFDictionaryGetValue(anItem, CFSTR("Description")), aPID);
                  }
                else
                  {
                    if (gDebugFlag) debug(CFSTR("Finished %@ (%d)\n"), CFDictionaryGetValue(anItem, CFSTR("Description")), aPID);
                  }
                displayProgress(aStartupContext->aDisplayContext, ((float)CFDictionaryGetCount(aStartupContext->aStatusDict)/((float)aStartupContext->aServicesCount + 1.0)));
              }

            /* If the item failed to start, then add it to the failed list */
            if (WEXITSTATUS(aStatus) || WTERMSIG(aStatus) || WCOREDUMP(aStatus))
              {
                CFDictionarySetValue(anItem, kErrorKey, kErrorReturnNonZero);
                AddItemToFailedList(aStartupContext, anItem);
              }

            /* Remove the item from the waiting list regardless if it was successful or it failed. */
            RemoveItemFromWaitingList(aStartupContext, anItem);
          }
      }
      
    if (aTerminationContext) free(aTerminationContext);

    
    /* Stop the current run loop so the system_starter engine will cycle and try to start any newly eligible items */
    CFRunLoopStop(CFRunLoopGetCurrent());
}
示例#14
0
//------------------------------------------------------------------------------
// IOMIGMachPortGetPort
//------------------------------------------------------------------------------
mach_port_t IOMIGMachPortGetPort(IOMIGMachPortRef migPort)
{
    return CFMachPortGetPort(migPort->port);
}
IOReturn IOPSCreatePowerSource(
    IOPSPowerSourceID *outPS,
    CFStringRef powerSourceType)
{
    IOPSPowerSourceID           newPS = NULL;
    mach_port_t                 pm_server = MACH_PORT_NULL;

    char                        psType[kMaxPSTypeLength];

    char                        scdsKey[kMaxSCDSKeyLength];

    mach_port_t                 local_port = MACH_PORT_NULL;
    int                         return_code = kIOReturnSuccess;
    kern_return_t               kr = KERN_SUCCESS;
    IOReturn                    ret = kIOReturnError;

    if (!powerSourceType || !outPS)
        return kIOReturnBadArgument;

    // newPS - This tracking structure must be freed by IOPSReleasePowerSource()

    newPS = calloc(1, sizeof(struct OpaqueIOPSPowerSourceID));

    if (!newPS)
        return kIOReturnVMError;

    // We allocate a port in our namespace, and pass it to configd. 
    // If this process dies, configd will cleanup  our unattached power sources.

    newPS->configdConnection = CFMachPortCreate(kCFAllocatorDefault, NULL, NULL, NULL);

    if (newPS->configdConnection)
        local_port = CFMachPortGetPort(newPS->configdConnection);

    if (MACH_PORT_NULL == local_port) {
        ret = kIOReturnInternalError;
        goto fail;
    }

    if (!CFStringGetCString(powerSourceType, psType, sizeof(psType), kCFStringEncodingMacRoman)) {
        ret = kIOReturnBadMedia;
        goto fail;
    }
    
    ret = _pm_connect(&pm_server);
    if(kIOReturnSuccess != ret) {
        ret = kIOReturnNotOpen;
        goto fail;
    }
    
    kr = io_pm_new_pspowersource(
            pm_server, 
            local_port,     // in: mach port
            psType,         // in: type name
            scdsKey,        // out: SCDS key
            &return_code);  // out: Return code

    if(KERN_SUCCESS != kr) {
        ret = kIOReturnNotResponding;
        goto fail;
    }

    _pm_disconnect(pm_server);

    newPS->scdsKey = CFStringCreateWithCString(0, scdsKey, kCFStringEncodingUTF8);

// success:
    *outPS = newPS;
    return (IOReturn)return_code;

fail:
    if (newPS)
        free(newPS);
    if (IO_OBJECT_NULL != pm_server)
        _pm_disconnect(pm_server);
    *outPS = NULL;

    return ret;
}
示例#16
0
CFRunLoopSourceRef DACommandCreateRunLoopSource( CFAllocatorRef allocator, CFIndex order )
{
    /*
     * Create a CFRunLoopSource for DACommand callbacks.
     */

    CFRunLoopSourceRef source = NULL;

    pthread_mutex_lock( &__gDACommandRunLoopSourceLock );

    /*
     * Initialize our minimal state.
     */

    if ( __gDACommandRunLoopSourcePort == NULL )
    {
        /*
         * Create the global CFMachPort.  It will be used to post jobs to the run loop.
         */

        __gDACommandRunLoopSourcePort = CFMachPortCreate( kCFAllocatorDefault, __DACommandRunLoopSourceCallback, NULL, NULL );

        if ( __gDACommandRunLoopSourcePort )
        {
            /*
             * Set up the global CFMachPort.  It requires no more than one queue element.
             */

            mach_port_limits_t limits = { 0 };

            limits.mpl_qlimit = 1;

            mach_port_set_attributes( mach_task_self( ),
                                      CFMachPortGetPort( __gDACommandRunLoopSourcePort ),
                                      MACH_PORT_LIMITS_INFO,
                                      ( mach_port_info_t ) &limits,
                                      MACH_PORT_LIMITS_INFO_COUNT );
        }

        if ( __gDACommandRunLoopSourcePort )
        {
            /*
             * Set up the global signal handler to catch child status changes from BSD.
             */

            sig_t sig;

            sig = signal( SIGCHLD, __DACommandSignal );

            if ( sig == SIG_ERR )
            {
                CFRelease( __gDACommandRunLoopSourcePort );

                __gDACommandRunLoopSourcePort = NULL;
            }
        }
    }

    /*
     * Obtain the CFRunLoopSource for our CFMachPort.
     */

    if ( __gDACommandRunLoopSourcePort )
    {
        source = CFMachPortCreateRunLoopSource( allocator, __gDACommandRunLoopSourcePort, order );
    }

    pthread_mutex_unlock( &__gDACommandRunLoopSourceLock );

    return source;
}
static void
rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
{
	SCDynamicStoreRef		store		= (SCDynamicStoreRef)info;
	SCDynamicStorePrivateRef	storePrivate	= (SCDynamicStorePrivateRef)store;

#ifdef	DEBUG
	SCLog(_sc_verbose, LOG_DEBUG,
	      CFSTR("schedule notifications for mode %@"),
	      (rl != NULL) ? mode : CFSTR("libdispatch"));
#endif	/* DEBUG */

	if (storePrivate->rlList == NULL) {
		CFMachPortContext	context		= { 0
							  , (void *)store
							  , CFRetain
							  , CFRelease
							  , notifyMPCopyDescription
							  };
		mach_port_t		oldNotify;
		mach_port_t		port;
		int			sc_status;
		kern_return_t		status;

#ifdef	DEBUG
		SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  activate callback runloop source"));
#endif	/* DEBUG */

		/* Allocating port (for server response) */
		status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
		if (status != KERN_SUCCESS) {
			SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_allocate(): %s"), mach_error_string(status));
			return;
		}

		status = mach_port_insert_right(mach_task_self(),
						port,
						port,
						MACH_MSG_TYPE_MAKE_SEND);
		if (status != KERN_SUCCESS) {
			/*
			 * We can't insert a send right into our own port!  This should
			 * only happen if someone stomped on OUR port (so let's leave
			 * the port alone).
			 */
			SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_insert_right(): %s"), mach_error_string(status));
			return;
		}

		/* Request a notification when/if the server dies */
		status = mach_port_request_notification(mach_task_self(),
							port,
							MACH_NOTIFY_NO_SENDERS,
							1,
							port,
							MACH_MSG_TYPE_MAKE_SEND_ONCE,
							&oldNotify);
		if (status != KERN_SUCCESS) {
			/*
			 * We can't request a notification for our own port!  This should
			 * only happen if someone stomped on OUR port (so let's leave
			 * the port alone).
			 */
			SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_request_notification(): %s"), mach_error_string(status));
			return;
		}

		if (oldNotify != MACH_PORT_NULL) {
			SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule(): oldNotify != MACH_PORT_NULL"));
		}

	    retry :

		__MACH_PORT_DEBUG(TRUE, "*** rlsSchedule", port);
		status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status);

		if (__SCDynamicStoreCheckRetryAndHandleError(store,
							     status,
							     &sc_status,
							     "rlsSchedule notifyviaport()")) {
			goto retry;
		}

		if (status != KERN_SUCCESS) {
			if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
				/* remove the send right that we tried (but failed) to pass to the server */
				(void) mach_port_deallocate(mach_task_self(), port);
			}

			/* remove our receive right  */
			(void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
			return;
		}

		if (sc_status != kSCStatusOK) {
			/* something [else] didn't work, remove our receive right  */
			(void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
			return;
		}

		__MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after notifyviaport)", port);
		storePrivate->rlsNotifyPort = _SC_CFMachPortCreateWithPort("SCDynamicStore",
									   port,
									   rlsCallback,
									   &context);
		storePrivate->rlsNotifyRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->rlsNotifyPort, 0);

		storePrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	}

	if ((rl != NULL) && (storePrivate->rlsNotifyRLS != NULL)) {
		if (!_SC_isScheduled(store, rl, mode, storePrivate->rlList)) {
			/*
			 * if we are not already scheduled with this runLoop / runLoopMode
			 */
			CFRunLoopAddSource(rl, storePrivate->rlsNotifyRLS, mode);
			__MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after CFRunLoopAddSource)", CFMachPortGetPort(storePrivate->rlsNotifyPort));
		}

		_SC_schedule(store, rl, mode, storePrivate->rlList);
	}

	return;
}
Boolean
SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue)
{
	dispatch_group_t		drainGroup	= NULL;
	dispatch_queue_t		drainQueue	= NULL;
	dispatch_group_t		group		= NULL;
	mach_port_t			mp;
	Boolean				ok		= FALSE;
	dispatch_source_t		source;
	SCDynamicStorePrivateRef	storePrivate	= (SCDynamicStorePrivateRef)store;

	if (store == NULL) {
		// sorry, you must provide a session
		_SCErrorSet(kSCStatusNoStoreSession);
		return FALSE;
	}

	if (queue == NULL) {
		if (storePrivate->dispatchQueue == NULL) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}

		ok = TRUE;
		goto cleanup;
	}

	if (storePrivate->server == MACH_PORT_NULL) {
		// sorry, you must have an open session to play
		_SCErrorSet(kSCStatusNoStoreServer);
		return FALSE;
	}

	if ((storePrivate->dispatchQueue != NULL) || (storePrivate->rls != NULL)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if (storePrivate->notifyStatus != NotifierNotRegistered) {
		// sorry, you can only have one notification registered at once...
		_SCErrorSet(kSCStatusNotifierActive);
		return FALSE;
	}

	/*
	 * mark our using of the SCDynamicStore notifications, create and schedule
	 * the notification port (storePrivate->rlsNotifyPort), and a bunch of other
	 * "setup"
	 */
	storePrivate->notifyStatus = Using_NotifierInformViaDispatch;
	rlsSchedule((void*)store, NULL, NULL);
	if (storePrivate->rlsNotifyPort == NULL) {
		/* if we could not schedule the notification */
		_SCErrorSet(kSCStatusFailed);
		goto cleanup;
	}

	// retain the dispatch queue
	storePrivate->dispatchQueue = queue;
	dispatch_retain(storePrivate->dispatchQueue);

	//
	// We've taken a reference to the callers dispatch_queue and we
	// want to hold on to that reference until we've processed any/all
	// notifications.  To facilitate this we create a group, dispatch
	// any notification blocks to via that group, and when the caller
	// has told us to stop the notifications (unschedule) we wait for
	// the group to empty and use the group's finalizer to release
	// our reference to the SCDynamicStore.
	//
	group = dispatch_group_create();
	storePrivate->dispatchGroup = group;
	CFRetain(store);
	dispatch_set_context(storePrivate->dispatchGroup, (void *)store);
	dispatch_set_finalizer_f(storePrivate->dispatchGroup, (dispatch_function_t)CFRelease);

	// create a dispatch source for the mach notifications
	mp = CFMachPortGetPort(storePrivate->rlsNotifyPort);
	source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, queue);
	if (source == NULL) {
		SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_create() failed"));
		_SCErrorSet(kSCStatusFailed);
		goto cleanup;
	}

	dispatch_source_set_event_handler(source, ^{
		kern_return_t	kr;
		mach_msg_id_t	msgid;
		union {
			u_int8_t			buf[sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE];
			mach_msg_empty_rcv_t		msg;
			mach_no_senders_notification_t	no_senders;
		} notify_msg;

		kr = mach_msg(&notify_msg.msg.header,	// msg
			      MACH_RCV_MSG,		// options
			      0,			// send_size
			      sizeof(notify_msg),	// rcv_size
			      mp,			// rcv_name
			      MACH_MSG_TIMEOUT_NONE,	// timeout
			      MACH_PORT_NULL);		// notify
		if (kr != KERN_SUCCESS) {
			SCLog(TRUE, LOG_ERR,
			      CFSTR("SCDynamicStore notification handler, kr=0x%x"),
			      kr);
			return;
		}

		msgid = notify_msg.msg.header.msgh_id;

		CFRetain(store);
		dispatch_group_async(group, queue, ^{
			if (msgid == MACH_NOTIFY_NO_SENDERS) {
				// re-establish notification and inform the client
				(void)__SCDynamicStoreReconnectNotifications(store);
			}
			rlsPerform(storePrivate);
			CFRelease(store);
		});
	});
static void
rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode)
{
	CFIndex				n		= 0;
	SCDynamicStoreRef		store		= (SCDynamicStoreRef)info;
	SCDynamicStorePrivateRef	storePrivate	= (SCDynamicStorePrivateRef)store;

#ifdef	DEBUG
	SCLog(_sc_verbose, LOG_DEBUG,
	      CFSTR("cancel notifications for mode %@"),
	      (rl != NULL) ? mode : CFSTR("libdispatch"));
#endif	/* DEBUG */

	if ((rl != NULL) && (storePrivate->rlsNotifyRLS != NULL)) {
		if (_SC_unschedule(store, rl, mode, storePrivate->rlList, FALSE)) {
			/*
			 * if currently scheduled on this runLoop / runLoopMode
			 */
			n = CFArrayGetCount(storePrivate->rlList);
			if (n == 0 || !_SC_isScheduled(store, rl, mode, storePrivate->rlList)) {
				/*
				 * if we are no longer scheduled to receive notifications for
				 * this runLoop / runLoopMode
				 */
				CFRunLoopRemoveSource(rl, storePrivate->rlsNotifyRLS, mode);
			}
		}
	}

	if (n == 0) {
		int		sc_status;
		kern_return_t	status;

#ifdef	DEBUG
		SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  cancel callback runloop source"));
#endif	/* DEBUG */
		__MACH_PORT_DEBUG((storePrivate->rlsNotifyPort != NULL),
				  "*** rlsCancel",
				  CFMachPortGetPort(storePrivate->rlsNotifyPort));

		if (storePrivate->rlList != NULL) {
			CFRelease(storePrivate->rlList);
			storePrivate->rlList = NULL;
		}

		if (storePrivate->rlsNotifyRLS != NULL) {
			/* invalidate & remove the run loop source */
			CFRunLoopSourceInvalidate(storePrivate->rlsNotifyRLS);
			CFRelease(storePrivate->rlsNotifyRLS);
			storePrivate->rlsNotifyRLS = NULL;
		}

		if (storePrivate->rlsNotifyPort != NULL) {
			mach_port_t	mp;

			mp = CFMachPortGetPort(storePrivate->rlsNotifyPort);
			__MACH_PORT_DEBUG((storePrivate->rlsNotifyPort != NULL),
					  "*** rlsCancel (before invalidating/releasing CFMachPort)",
					  mp);

			/* invalidate and release port */
			CFMachPortInvalidate(storePrivate->rlsNotifyPort);
			CFRelease(storePrivate->rlsNotifyPort);
			storePrivate->rlsNotifyPort = NULL;

			/* and, finally, remove our receive right  */
			(void)mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_RECEIVE, -1);
		}

		if (storePrivate->server != MACH_PORT_NULL) {
			status = notifycancel(storePrivate->server, (int *)&sc_status);

			(void) __SCDynamicStoreCheckRetryAndHandleError(store,
									status,
									&sc_status,
									"rlsCancel notifycancel()");

			if (status != KERN_SUCCESS) {
				return;
			}
		}
	}

	return;
}
示例#20
0
SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnDatap) {
    struct __CFMessagePortMachMessage *sendmsg;
    CFRunLoopRef currentRL = CFRunLoopGetCurrent();
    CFRunLoopSourceRef source = NULL;
    CFDataRef reply = NULL;
    int64_t termTSR;
    uint32_t sendOpts = 0, sendTimeOut = 0;
    int32_t desiredReply;
    Boolean didRegister = false;
    kern_return_t ret;

//#warning CF: This should be an assert
    // if (!__CFMessagePortIsRemote(remote)) return -999;
    if (!__CFMessagePortIsValid(remote)) return kCFMessagePortIsInvalid;
    __CFMessagePortLock(remote);
    if (NULL == remote->_replyPort) {
	CFMachPortContext context;
	context.version = 0;
	context.info = remote;
	context.retain = (const void *(*)(const void *))CFRetain;
	context.release = (void (*)(const void *))CFRelease;
	context.copyDescription = (CFStringRef (*)(const void *))__CFMessagePortCopyDescription;
	remote->_replyPort = CFMachPortCreate(CFGetAllocator(remote), __CFMessagePortReplyCallBack, &context, NULL);
    }
    remote->_convCounter++;
    desiredReply = -remote->_convCounter;
    CFDictionarySetValue(remote->_replies, (void *)desiredReply, NULL);
    sendmsg = __CFMessagePortCreateMessage(CFGetAllocator(remote), false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : 0));
    __CFMessagePortUnlock(remote);
    if (replyMode != NULL) {
        source = CFMachPortCreateRunLoopSource(CFGetAllocator(remote), remote->_replyPort, -100);
        didRegister = !CFRunLoopContainsSource(currentRL, source, replyMode);
	if (didRegister) {
            CFRunLoopAddSource(currentRL, source, replyMode);
	}
    }
    if (sendTimeout < 10.0*86400) {
	// anything more than 10 days is no timeout!
	sendOpts = MACH_SEND_TIMEOUT;
	sendTimeout *= 1000.0;
	if (sendTimeout < 1.0) sendTimeout = 0.0;
	sendTimeOut = floor(sendTimeout);
    }
    ret = mach_msg((mach_msg_header_t *)sendmsg, MACH_SEND_MSG|sendOpts, sendmsg->head.msgh_size, 0, MACH_PORT_NULL, sendTimeOut, MACH_PORT_NULL);
    CFAllocatorDeallocate(CFGetAllocator(remote), sendmsg);
    if (KERN_SUCCESS != ret) {
	if (didRegister) {
	    CFRunLoopRemoveSource(currentRL, source, replyMode);
	    CFRelease(source);
	}
	if (MACH_SEND_TIMED_OUT == ret) return kCFMessagePortSendTimeout;
	return kCFMessagePortTransportError;
    }
    if (replyMode == NULL) {
	return kCFMessagePortSuccess;
    }
    CFRetain(remote); // retain during run loop to avoid invalidation causing freeing
    _CFMachPortInstallNotifyPort(currentRL, replyMode);
    termTSR = mach_absolute_time() + __CFTimeIntervalToTSR(rcvTimeout);
    for (;;) {
	CFRunLoopRunInMode(replyMode, __CFTSRToTimeInterval(termTSR - mach_absolute_time()), true);
	// warning: what, if anything, should be done if remote is now invalid?
	reply = CFDictionaryGetValue(remote->_replies, (void *)desiredReply);
	if (NULL != reply || termTSR < (int64_t)mach_absolute_time()) {
	    break;
	}
	if (!CFMessagePortIsValid(remote)) {
	    // no reason that reply port alone should go invalid so we don't check for that
	    break;
	}
    }
    // Should we uninstall the notify port?  A complex question...
    if (didRegister) {
        CFRunLoopRemoveSource(currentRL, source, replyMode);
	CFRelease(source);
    }
    if (NULL == reply) {
	CFDictionaryRemoveValue(remote->_replies, (void *)desiredReply);
	CFRelease(remote);
	return CFMessagePortIsValid(remote) ? kCFMessagePortReceiveTimeout : -5;
    }
    if (NULL != returnDatap) {
	*returnDatap = ((void *)0xffffffff == reply) ? NULL : reply;
    } else if ((void *)0xffffffff != reply) {
	CFRelease(reply);
    }
    CFDictionaryRemoveValue(remote->_replies, (void *)desiredReply);
    CFRelease(remote);
    return kCFMessagePortSuccess;
}
void MachRunLoopServer::cfInvalidate(CFMachPortRef cfPort, void *context)
{
	reinterpret_cast<MachRunLoopServer *>(context)->notifyDeadName(CFMachPortGetPort(cfPort));
	//@@@ should we CFRelease cfPort here?
}
示例#22
0
/*
 * For now, this requires a single argument, which is the service file.
 * The service file is formatted as described in the SLP API specification.
 */
int main(int argc, char *pcArgv[])
{
    SAState 			sa;
    struct sockaddr_in	sin; /* for active da discovery */
    int 				err = 0;
    const char *		pcScopes;
	struct rlimit 		rlim;
	rlim_t				i;

// first just see if they are only checking the version...
    if ( argc > 1 && strcmp(pcArgv[1], "-v") == 0 )
    {
        // they just want the version number
        fprintf( stdout, "%s\n", SLPD_VERSION );
        exit(0);
    }
    
#ifdef ENABLE_SLP_LOGGING
    SLP_LOG( SLP_LOG_STATE, "*** slpd started ***" );
#endif	
// we need to close all the open file descriptors of who ever launched us!

	if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0 )
	{
		SLPLOG(SLP_LOG_ERR, "Failed to getrlimit!");
		rlim.rlim_cur = FD_SETSIZE;
	}
	
	for ( i=rlim.rlim_cur; i>=0; i-- )
		close(i);

	// Ignore SIGPIPE's mysteriously generated by AFP/ServerControl.
	struct sigaction	sSigAction, sSigOldAction ;

	sigemptyset (&sSigAction.sa_mask) ;
	sSigAction.sa_handler = (void (*) (int)) SIG_IGN ;
	::sigaction (SIGPIPE, &sSigAction, &sSigOldAction) ;


	mach_port_limits_t	limits = { 1 };
	CFMachPortRef		port;
	
	port = CFMachPortCreate(NULL,(CFMachPortCallBack)SignalMessageHandler,NULL,NULL);
	CFRunLoopAddSource(CFRunLoopGetCurrent(),CFMachPortCreateRunLoopSource(NULL,port,0),kCFRunLoopCommonModes);
	
	gSignalPort = CFMachPortGetPort(port);
	mach_port_set_attributes(mach_task_self(),gSignalPort,MACH_PORT_LIMITS_INFO,
							 (mach_port_info_t)&limits,sizeof(limits) / sizeof(natural_t));
	
	signal(SIGINT,SignalHandler);
    
	if ( IsNetworkSetToTriggerDialup() )
	{
		SLPLOG(SLP_LOG_ERR, "slpd: Network is set to auto dial ppp, - abort");
		return 0;
	}
	
    OPEN_NETWORKING();		// have to call this to intialize our lock mutex
    InitSLPRegistrar();

    memset( &sa, 0, sizeof(SAState) );

    err = reset_slpd( argc, pcArgv, &sin, &sa );		// do initialization and process config file
   
    if ( err )
    {
        SLPLOG(SLP_LOG_ERR, "slpd: could not do initial setup - abort");
        return err;
    }
    
    SDatexit(exit_handler);

	/*
     *	time to daemonize
     */

    /*
    *  initialize network stuff
    */
    if (mslpd_init_network(&sa) != SLP_OK)
    {
    	SLPLOG(SLP_LOG_FAIL, "slpd: could not init networking - abort");
        return -3;
    }

	/*
    * save socket handles so we can free them on exit.
    */
    global_resources.sdUDP = sa.sdUDP;
    global_resources.sdTCP = sa.sdTCP;

    if ((pcScopes = SLPGetProperty("net.slp.useScopes"))==NULL)
    {
        pcScopes = SLP_DEFAULT_SCOPE;
    }
    
    InitializeListeners( &sa );
    
	StartSLPUDPListener( &sa );
	StartSLPTCPListener( &sa );
    
    if ( AreWeADirectoryAgent() )
	{
        StartSLPDAAdvertiser( &sa );
		SLPRegistrar::TheSLPR()->EnableRAdminNotification();
	}
	
    /*
    *  discover DAs actively
    *  each time one is found, local registration is immediately forward
    *
    *  NOTE:  This is very simple-minded.  If there are many DAs or any of
    *  them are slow - the forwarding will take too long and the active
    *  discovery will time out before all DAs are found.  A better way to
    *  do this would be to simply go through all DAs after this round and
    *  forward to them sequentially.
    */
	InitializeSLPDARegisterer( &sa );

    StartSLPDALocator( (void *)mslpd_daadvert_callback, CFRunLoopGetCurrent(), &sa );

    sa.pdat = GetGlobalDATable();

    /*
    * The main loop is such that it simply launches handlers.  These could
    * be done in a separate thread.  Note that the SAState is read only
    * except for the fd_set, which should only be set in this thread.
    * If the mslpd accepts register/deregister ipc commands in the future,
    * the SAStore.store field will require locks.
    */

#ifdef ENABLE_SLP_LOGGING
    SLP_LOG( SLP_LOG_MSG, "slpd: initialization finished");
#endif    
    err = RunSLPInternalProcessListener( &sa );		// this is just going to listen for IPC communications
    
    CFRunLoopRun();		// this will run forever until interrupted from the command line or CFRunLoopStop
    
#ifdef ENABLE_SLP_LOGGING
    SLP_LOG( SLP_LOG_MSG, "slpd: exiting");
#endif    
    
    return _Signal;
}
示例#23
0
static mach_port_t __CFMessagePortGetPort(void *info) {
    CFMessagePortRef ms = info;
    return CFMachPortGetPort(ms->_port);
}
示例#24
0
文件: IPC.c 项目: aosm/Startup
static mach_port_t getIPCPort(void* anInfo)
{
    return anInfo ? CFMachPortGetPort((CFMachPortRef)anInfo) : MACH_PORT_NULL;
}