| Main |

November 24, 2009

Great day

OK, so yesterday sucked. One of my guys’ computers went wrong, and he cycles to work and had left his laptop at home, so I had to drive him there, in the rain, to pick it up (much to the irritation of his wife, who had been hoping to use it — but it is company property so the outcome of that discussion was pretty obvious at the outset). Then I spent ages on the phone trying to locate a replacement, until the extremely helpful chap at the Apple Business Store (hi Rod!) sorted me out with next day delivery on a new one.

Then I spent the rest of the day doing customer support. We all do that at Coriolis Systems; it’s good that we software developers get involved with real customers and see what the real problems are with our products. All too often people are divorced from the actual customers because they have (sometimes layers) of customer support staff in between them and the real world. We don’t. The downside of that is that it can be a bit of a drag at times, dealing with yet another “I forgot my password”, “My e-mail address is wrong” query, punctuated with occasional customer angry that “we didn’t reply” (translation: they, their IT department, and/or their ISP are not competent to run a mail server, but are trying to anyway, and have cunningly configured it to ignore/junk/bounce e-mail from us).

Anyway, the remainder of yesterday was spent doing that. We always get a lot of mail to deal with on a Monday, because we don’t work weekends, but I really don’t like not making progress with whatever else I’m working on.

Today, on the other hand, was great. Made plenty of progress with what I’ve been working on. It still isn’t perfect (just checked it remotely, and it’s broken :-)), but it’s definitely getting there, which is good news indeed, as it means I’ll soon be back working on what I was doing before (both more interesting and more fun, quite frankly).

Also managed to do a load of housework when I got home, so that’s good too. Surprising how much work it is to keep on top of all the housework, but I really do love living in my new house :-) :-)

November 12, 2009

Cross-process semaphores with timeouts on OS X

Someone on darwin-dev recently asked how to go about obtaining a cross-process semaphore that can be waited on with a timeout on OS X.

POSIX semaphores currently don’t support this feature on OS X; nor do System V semaphores. Mach semaphores do support timeouts (see /usr/include/mach/semaphore.h), but it isn’t immediately obvious how to pass one to another process.

Anyway, I thought I’d stick together a simple Mach server to implement named semaphores; the idea is very simple… 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 simply 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 called 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:

  1. If you’re going to use this code directly in your program, please don’t change the .defs file without altering the definition of SEMSRV_SERVICE to a name that starts with your own reverse domain prefix. Doing that would break anything that uses this code literally as-is.

  2. In a normal program, you probably want to try spawning the semsrv process 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.

  3. The semsrv program doesn’t daemonize itself. This might matter to you, or it might not.

  4. It’s possible that you might be interested in re-writing the server to use launchd so that it starts automatically and you don’t need to worry about point 2 (above). Note though that doing that will mean your program needs to install a suitable launch daemon property list, which might be more of a headache than it’s worth.

  5. This code is only really intended as a sample, and has had limited testing. There is obviously no warranty or anything like that.

  6. The code is in the Public Domain. It is not subject to copyright and therefore has no license. If you work for someone too stupid to understand the words Public Domain, you can simply slap a BSD or MIT license on it and carry on with what you were doing.

The code can be built by typing make at a command prompt after changing into its directory. It has a very simple (and not perfect) Makefile, but I can’t be bothered with anything more elaborate. You could add the files to an Xcode project instead if you wanted, in which case you’d need to make Xcode run mig if it doesn’t already know to do that.

To try a few simple experiments, build the code, then enter ./semsrv & at a Terminal prompt to start the server. You can then use the ./semtest program to try various things, e.g.

$ tar xjf semsrv.tar.bz2
$ cd semsrv
$ make
mig semsrv.defs
cc -g -W -Wall   -c -o semsrvServer.o semsrvServer.c
g++ -g -W -Wall   -c -o server.o server.cc
g++ -g -W -Wall  semsrvServer.o server.o  -o semsrv
cc -g -W -Wall   -c -o client.o client.c
cc -g -W -Wall   -c -o semsrvUser.o semsrvUser.c
cc -g -W -Wall  client.o semsrvUser.o  -o semtest
$ ./semsrv &
$ ./semtest create foo
Created foo: 4099
$ ./semtest signal foo
Signalled foo
$ ./semtest wait foo
Waiting for foo...done
$ ./semtest get foo
Got foo: 4099
$ ./semtest create foo
Got foo (already exists): 4099
$ ./semtest destroy foo
Destroyed foo

Obviously to test more interesting behaviour, you’ll want more than one Terminal window…

The code is in this archive file.