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 PROTECTED]>
Voodoo Ergonomics Inc. <http://voodooergonomics.com/>



Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to