Cross-process semaphores with timeouts on OS X
OS X provides three kinds of semaphores by default; POSIX semaphores, System V sempahores, and Mach semaphores. Of those, neither the POSIX form nor the System V form support any kind of timeout, and while Mach semaphores do support a timeout, it isn’t immediately obvious how to pass one to another process.
semsrv is here to solve this problem. It’s a simple Mach server that
implements named semaphores; when you want a semaphore, you ask the server to
create it for you, giving it a name. If it already exists, the server will
return the existing semaphore object. If not, it will create a new Mach
semaphore and return that.
Once you have the
semaphore_t port value, you use it just as if you had
semaphore_create() yourself. When you’re done with it, you can use
mach_port_destroy() to release the port in your own process. You won’t be
able to destroy the semaphore using
semaphore_destroy(), because your task
doesn’t own it.
A few notes:
If you’re going to use this code directly in your program, please don’t change the
.defsfile without altering the definition of
SEMSRV_SERVICEto a name that starts with *your own* reverse domain prefix. Doing that would break anything that uses this code literally as-is.
In a normal program, you probably want to try spawning the
semsrvprocess in the background. If another program has already started the server with the same service name, your copy will fail, but that’s OK because you can just use the other copy.
semsrvprogram doesn’t daemonize itself. This might matter to you, or it might not.
It’s possible that you might be interested in re-writing the server to use
launchdso that it starts automatically and you don’t need to worry about point 2 (above). Note that doing that will mean your program needs to install a suitable launch daemon property list.
This code is only really intended as a sample, and has had limited testing.
The code can be built by typing
make at a command prompt. It has a very
simple (and not perfect)
Makefile, but I can’t be bothered with anything
If you just want to kick the tyres, try:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Obviously to test more interesting behaviour, you’ll want more than one Terminal window…
You can grab the code from the mercurial repository.