[launchd-dev] Distributed Objects communication with a launchd "on-demand" daemon

Damien Sorresso dsorresso at apple.com
Sun Dec 20 19:30:35 PST 2009


On Dec 17, 2009, at 10:47 AM, Frank Rizzo wrote:
> I believe that I now have solved my problem using a launchd "on-demand" daemon with Distributed Objects (DO).
> 
> I was only using TCP ports here for initial development because some of the launchd "on-demand" sample code does and because I had been unable to create an NSMachPort with the mach_port_t value I received from launchd.  However, while writing a response to a replay to my message (which I had originally posted on the Cocoa-dev list), I caught a trivial programming error that fixed my NSMachPort creation problem (they were coming back nil) and also allowed DO to work with the launchd daemon "on-demand."  I have not yet tried the UNIX domain socket approach to client<->daemon communication DO yet, and since I believe that Mach ports are preferred for DO I do not intend to at this point.   
> 
> Here is the mach services version of my code (which works with the launchd daemon "on-demand"):
> 
> // TestDaemonLaunchd.plist

Please name your plist in the reverse-DNS style. In your case, com.example.TestDaemon. We intend to begin enforcing this convention sometime down the line.

> <dict>
> 	<key>ServiceIPC</key>
> 	<true/>
> 	<key>MachServices</key>
> 	<dict>
> 		<key>com.example.TestDaemon</key>
> 		</true>
> 	</dict>
> 	<key>OnDemand</key>
> 	<true/>
> 	<key>Label</key>
> 	<string>com.example.TestDaemon</string>
> 	<key>ProgramArguments</key>
> 	<array>
> 		<string>/path/to/TestDaemon</string>
> 	</array>
> </dict>

The ServiceIPC and OnDemand keys aren't needed anymore. They were only relevant on Tiger.

> //  TestDaemon.m
> 
> int main (int argc, const char * argv[]) {
> 
>    	NSAutoreleasePool *pool = [NSAutoreleasePool new];	
> 
> // NOTE: Getting the Mach port descriptor (mp) from launchd.
>     	launch_data_t checkinRequest = launch_data_new_string(LAUNCH_KEY_CHECKIN);
> 	launch_data_t checkinResponse = launch_msg(checkinRequest);
> 	launch_data_t machServicesDict = launch_data_dict_lookup(checkinResponse, LAUNCH_JOBKEY_MACHSERVICES);
> 	launch_data_t machPort = launch_data_dict_lookup(machServicesDict, "com.example.TestDaemon");
> 
> 	mach_port_t mp = launch_data_get_machport(machPort);
> 
>         launch_data_free(checkinResponse);
>         launch_data_free(checkinRequest);
> 
> 	NSMachPort *receivePort = [[NSMachPort alloc] initWithMachPort:mp];
> 	NSConnection *connection = [NSConnection connectionWithReceivePort:receivePort sendPort:nil];
> 	[receivePort release];
> 
> 	id testObject = [NSObject new];
> 	[connection setRootObject:testObject];
> 
> 	[[NSRunLoop currentRunLoop] run];
> 
> 	[testObject release];
>     	[pool release];
>    	return 0;
> }

Just use bootstrap_check_in() to obtain your Mach port. The launch_msg() API is pretty crufty and only needed for obtaining socket file descriptors.

> //  TestClient.m
> int main (int argc, const char * argv[]) {
> 
>    	NSAutoreleasePool *pool = [NSAutoreleasePool new];
> 
> 	NSConnection *connection = [NSConnection connectionWithRegisteredName:@"com. example.TestDaemon" host:nil];
> 
> 	[connection setRequestTimeout:10.0];
> 	[connection setReplyTimeout:10.0];
> 
> // NOTE: No NSPortTimeoutException is raised when used with an "on-demand" launchd daemon after switching to Mach ports for DO communication.
> 	id proxy = [connection rootProxy];
> 	[pool release];
>    	return 0;
> }

On Dec 18, 2009, at 8:21 PM, Frank Rizzo wrote:
> I have no intention of using DO for "cross-security domain communications."

Since this service is a daemon and anyone can look up the service, you are crossing security domains.
-- 
Damien Sorresso
BSD Engineering
Apple Inc.



More information about the launchd-dev mailing list