Archive for December, 2008

Manpage Monday: notify(3)

Monday, December 8th, 2008

notify(3) is a simple API that allows processes to poke other processes, and to be poked.

The API is similar to NSDistributedNotificationCenter, except that it's not object-oriented, it's not based on Foundation or CF, and it doesn't allow you to attach a property list to the notification.

You register in one of four ways:

notify_register_check
Sign up under a name, and get a registration token.
notify_register_signal
Have the system send your process a signal when another process posts a notification with a particular name. Also get a registration token.
notify_register_mach_port
Have the system send your process a message on a Mach port when another process posts a notification with a particular name. Also get a registration token.
notify_register_file_descriptor
Get a registration token, and have the system write that token to a file descriptor when another process posts a notification with a particular name.

Each of the last two functions will create the Mach port or file descriptor for you, unless you tell it to use one you already have. You do that by passing NOTIFY_REUSE.

All four functions give you a registration token (the first one does nothing else), which is simply a signed 32-bit integer. You can then use notify_check to poll that token to see whether any processes have posted a notification to it since the last time you checked. (I don't know how the other notification methods affect this—e.g., whether notify_check will ever return true if you got the token from notify_register_signal.)

You free the token using notify_cancel. This also closes any Mach ports or file descriptors you have associated with it. There is no way to disassociate them from the token or to cancel the token without closing the associated resources.

On the sending side, the API provides one function: notify_post. It takes one argument, which is the notification name; this is the same name that any receiving processes passed to their chosen notify_register_whatever function.

Leopard adds a new feature: you can associate a shared 64-bit number with a name using notify_set_state, and retrieve that number using notify_get_state. I suggest that you only use notify_set_state in a single process, as I can imagine race conditions occurring if two processes try to set state under the same name. If you need bidirectional communication, use two notification names (or a different means of communication, such as sockets or Mach ports).

Apple introduced the rest of the notify(3) API in Panther.

Updates to “How to work with a bound-to array”

Wednesday, December 3rd, 2008

Following an email conversation with Dave Dribin, I've updated my earlier post on how to work with a bound-to array.

The most critical update, and the reason for a new blog post to announce the update, is that you should not currently implement addObject: and removeObject: for an array property. KVO has a bug where it treats these as set accessors, even if the property is an array. This will result in crashes if you observe your object using plain KVO.

The workaround is to use indexed accessors:

[self insertObject:newFramistan inFramistansAtIndex:[self countOfFramistans]];

This is a little uglier than addFramistansObject:, but it doesn't crash.

The other update is that you need to implement both accessors in a pair. For example, for insertObject:inKeyAtIndex: to work, you must also implement removeObjectFromKeyAtIndex: (and vice versa). Otherwise, KVO won't override the one you did implement, so you won't get notifications for it.

I've filed bugs for both of these, and I've linked to both bugs from the older post.

Bad Behavior has blocked 250 access attempts in the last 7 days.