Пример #1
0
static int ListenUsingMach(size_t noteCount, const char **noteNames)
    // Implements the "listenMach" command.  Register for the noteCount 
    // notifications whose names are in the noteNames array.  Then read 
    // the notification Mach port, printing information about any 
    // notifications that arrive.
{
    int         retVal;
    uint32_t    noteErr;
    size_t      noteIndex;
    int         noteTokens[noteCount];
    mach_port_t port = MACH_PORT_NULL;
    
    // Register.  The first time around this loop fd == -1 and so we don't 
    // specify NOTIFY_REUSE.  notify_register_mach_port then allocates 
    // a Mach port and returns it in port.  For subsequent iterations 
    // we /do/ specify NOTIFY_REUSE and notify_register_mach_port just 
    // reuses the existing port.

    noteErr = NOTIFY_STATUS_OK;
    for (noteIndex = 0; noteIndex < noteCount; noteIndex++) {
        noteErr = notify_register_mach_port(
            noteNames[noteIndex], 
            &port, 
            (port == MACH_PORT_NULL) ? 0 : NOTIFY_REUSE, 
            &noteTokens[noteIndex]
        );
        if (noteErr != NOTIFY_STATUS_OK) {
            break;
        }
    }
    if (noteErr != NOTIFY_STATUS_OK) {
        PrintNotifyError("registration failed", noteNames[noteIndex], noteErr);
        retVal = EXIT_FAILURE;
    } else {
        kern_return_t           kr;
        mach_msg_empty_rcv_t    msg;

        // Listen for and print any incoming notifications.
        
        fprintf(stdout, "Listening using Mach:\n");
        fflush(stdout);
        do {
            msg.header.msgh_local_port = port;
            msg.header.msgh_size = sizeof(msg);
            kr = mach_msg_receive(&msg.header);
            if (kr == KERN_SUCCESS) {
                PrintToken(msg.header.msgh_id, noteCount, noteTokens, noteNames);
            }
        } while (kr == KERN_SUCCESS);
        
        fprintf(stderr, "error reading Mach message: %s (0x%x)\n", mach_error_string(kr), kr);
        retVal = EXIT_FAILURE;
    }
    
    return retVal;
}
Пример #2
0
int
OSMemoryNotificationCreate(OSMemoryNotificationRef *note)
{
	OSMemoryNotificationRef ref = malloc(sizeof(struct _OSMemoryNotification));

	if (NULL == ref) {
		return ENOMEM;
	}
	
	if (NOTIFY_STATUS_OK != notify_register_mach_port(kOSMemoryNotificationName, &ref->port, 0, &ref->token))
		return ENOMEM;

	*note = ref;

	return 0;
}
Пример #3
0
static int ListenUsingCoreFoundation(size_t noteCount, const char **noteNames)
    // Implements the "listenCF" command.  Register for the noteCount 
    // notifications whose names are in the noteNames array.  Then wrap the 
    // notification Mach port in a CFMachPort and use CF to read the notification 
    // messages, printing the information about any notifications that arrive 
    // from our CFMachPort callback.
{
    int         retVal;
    uint32_t    noteErr;
    size_t      noteIndex;
    int         noteTokens[noteCount];
    mach_port_t port = MACH_PORT_NULL;
    
    // Register.  The first time around this loop fd == -1 and so we don't 
    // specify NOTIFY_REUSE.  notify_register_mach_port then allocates 
    // a Mach port and returns it in port.  For subsequent iterations 
    // we /do/ specify NOTIFY_REUSE and notify_register_mach_port just 
    // reuses the existing port.

    noteErr = NOTIFY_STATUS_OK;
    for (noteIndex = 0; noteIndex < noteCount; noteIndex++) {
        noteErr = notify_register_mach_port(
            noteNames[noteIndex], 
            &port, 
            (port == MACH_PORT_NULL) ? 0 : NOTIFY_REUSE, 
            &noteTokens[noteIndex]
        );
        if (noteErr != NOTIFY_STATUS_OK) {
            break;
        }
    }
    if (noteErr != NOTIFY_STATUS_OK) {
        PrintNotifyError("registration failed", noteNames[noteIndex], noteErr);
        retVal = EXIT_FAILURE;
    } else {
        MyCFMachPortCallBackInfo    myInfo;
        CFMachPortContext           context = { 0 };
        CFMachPortRef               cfPort;
        Boolean                     shouldFreeInfo;
        CFRunLoopSourceRef          rls;
        
        // Set up the context structure for MyCFMachPortCallBack.
        
        myInfo.magic      = 'CFpI';
        myInfo.noteCount  = noteCount;
        myInfo.noteTokens = noteTokens;
        myInfo.noteNames  = noteNames;
        
        // Create the CFMachPort.
        
        context.info = &myInfo;
        cfPort = CFMachPortCreateWithPort(
            NULL, 
            port, 
            MyCFMachPortCallBack, 
            &context, 
            &shouldFreeInfo
        );
        assert(cfPort != NULL);
        
        // There can only be one CFMachPort for a given Mach port name.  Thus, 
        // if someone had already created a CFMachPort for "port", CFMachPort 
        // would not create a new CFMachPort but, rather, return the existing 
        // CFMachPort with the retain count bumped.  In that case it hasn't 
        // taken any 'reference' on the data in context; the context.info 
        // on the /previous/ CFMachPort is still in use, but the context.info 
        // that we supply is now superfluous.  In that case it returns 
        // shouldFreeInfo, telling us that we don't need to hold on to this 
        // information.
        //
        // In this specific case no one should have already created a CFMachPort 
        // for "port", so shouldFreeInfo should never be true.  If it is, it's 
        // time to worry!
        
        assert( ! shouldFreeInfo );
        
        // Add it to the run loop.
        
        rls = CFMachPortCreateRunLoopSource(NULL, cfPort, 0);
        assert(rls != NULL);

        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
        
        CFRelease(rls);
        
        // Run the run loop.
        
        fprintf(stdout, "Listening using Core Foundation:\n");
        fflush(stdout);
        
        CFRunLoopRun();

        fprintf(stderr, "CFRunLoopRun returned\n");
        retVal = EXIT_FAILURE;
    }
    
    return retVal;
}