Re: Daemon Advice?
Re: Daemon Advice?
- Subject: Re: Daemon Advice?
- From: Karl Moskowski <email@hidden>
- Date: Thu, 24 Jul 2008 18:20:57 -0400
On 24-Jul-08, at 5:52 PM, Chris Hanson wrote:
On Jul 23, 2008, at 1:09 PM, Karl Moskowski wrote:
I'm working on a Foundation tool to be used as a launchd daemon.
It's a Leopard-only GC app that uses FSEvents to watch for changed
files.
Can anyone offer any tips or guidance? Thanks.
I have a couple other tips, since you're writing a launch daemon
using Objective-C GC.
Some of this may not apply to your specific daemon, but it's stuff
to keep in mind in general when writing a Leopard-targeted
Foundation daemon that uses Objective-C GC. :)
(1) Do a launchd checkin.
I wrote a weblog post on this here:
launchd: Better than sliced bread!
http://chanson.livejournal.com/179229.html
Checking in with launchd will ensure that launchd actually passes
you the file descriptor you've asked for if you're running a service
that something is going to communicate with it. (It's also good
launchd hygiene.)
For example, your launchd property list can specify that your
service should be launched on-demand when a user connects to a
secure UNIX-domain socket. All processes subsequently launched by
launchd will get the path to this socket passed via an environment
variable you named, and your daemon when it checks in will actually
be passed a file descriptor for this socket. (You can even use that
socket for Distributed Objects via -[NSSocketPort
initWithProtocolFamily:socketType:protocol:socket:].)
(2) Start the threaded collector early on.
You can use objc_startCollectorThread() in <objc/objc-auto.h> to
ensure that the collector thread runs.
(3) Leverage NSRunLoop to run your "service loop."
Your example appears to be using it already, but for the archive's
sake, NSRunLoop is designed to be an abstract "event queue service
loop" for applications, regardless of whether they're UI
applications or not. If your daemon handles events (such as
commands from clients) you can treat them as a run loop source and
let the framework do the heavy lifting of multiplexing multiple
input sources for you.
Once through your run loop is also a good place to hint to the
collector that it should collect if necessary. A non-GC app would
probably bracket the run of the run loop in an autorelease pool. A
decent technique for this is to get the underlying CFRunLoop from
the NSRunLoop (they're NOT toll-free bridged) and add an appropriate
observer to it that gets callbacks at appropriate points.
(4) Use NSOperation for your work queue.
Since you're using Leopard, you can use NSOperation for your units
of work. That will be easier than creating your own work queue
system, and using OS-provided constructs like NSOperation can help
the system better balance its overall load because it can take a
holistic view that an app-implemented work queue can't.
Chris,
Excellent advice, and exactly what I was hoping for. Thanks.
I did a quick scan of your blog (I'll give it a more detailed read
tomorrow at work), and one thing stood out immediately. Hanging out
on the apple-cdsa mailing list, I found out that the preferred place
to put daemon executables is in /Library/PrivilegedHelperTools/ using
an Authorization Services-enabled installer. There may be permissions
issues in other locations (I'd originally tried to run my daemon from
within the app package - strange things happened, e.g., when I tried
to access keychain items). Apple has an example at:
<http://developer.apple.com/samplecode/BetterAuthorizationSample/>
----
Karl Moskowski <email@hidden>
Voodoo Ergonomics Inc. <http://voodooergonomics.com/>
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden