Method to Claim a "Name" Session-Wide, Reclaimed on Process Exit?

This is for macOS Cocoa apps. I've been using NSPortNameServer until its deprecation to claim a "name" for simple IPC that's automatically destroyed when the process that called -registerPort: exits for any reason. The purpose is to guard other processes using the same framework from clobbering each other trying to the the same thing (just the TASK for discussion purposes) when more than one are running at the same time. There's no information exchanged except to call "dibs" on this TASK, and ideally the solution we move to also works with sandboxing.

I've avoided filesystem semantics because files/directories/named semaphores all persist if the process that created them dies, which will litter that namespace, and most don't provide an efficient way of detecting whether the process that created them is still alive.

The processes don't need to exchange any data at all, just for one of them (the first to claim the privilege) to handle TASK during its lifetime. The other processes continue to receive the event notifications which would trigger the TASK, so if the claimant dies the next to respond will take the claim immediately. It's also important that this claim only be held session-wide, not machine-wide.

It doesn't look like notifyd, sem_open, and others provide this particular semantic, and the closest I got was an NSProgress published nominally to an aribtrary file/directory, but that seems more like API abuse, as would NSFileCoordinator (though that at least is closer). I don't see how holding this particular claim could be considered a security risk, so I would hope it could also work with sandboxing (e.g. not require an app group, etc).

Replies

Your currently implementing only works within one (presumbly) GUI login context. That is, if I have two GUI users logged in, both will be able to execute TASK simultaneously. Is that a known limitation? Or part of your design?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

That is both correct and my intent. TASK should only be performed by one process in a single GUI context (other sessions/context are not applicable), but two users logged in (fast-switching or other) would have to perform it independently and can't share the result.

I should point out that the claim here is to prevent clobbering (might be ignoreable, but I would rather not risk it), and I also want to avoid login agents or some other kind of login action, first to prevent doing work when the apps aren't open, and second to keep this particular part in-process and avoid having to ship extra plugins/services/etc for the TASK.

That is both correct and my intent.

OK. Next question: Earlier you wrote:

The purpose is to guard other processes using the same framework from clobbering each other trying to the the same thing … when more than one are running at the same time.

Is your product a (literal) framework? Or are you using framework in the generic sense?

Also, are their any restrictions on the client apps? Are these all apps you control? Or do you distribute this framework (or ‘framework’) to third parties? And do you need the client apps to support the App Sandbox?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

It is a literal framework used in several macOS Cocoa apps, which are all enterprise, source owned and maintained by us. Some are sandboxed, some are not (yet), nothing is distributed to third parties. The highest restriction I can think of for IPC is the app sandbox, so I would prefer the next solution work with it as well.

As there doesn't seem to be an easy answer, I think I'll try File Coordination.