Kevin Van Vechten <mailto:kvv@apple.com> wrote (Thursday, November 29, 2007 6:28 PM -0800):
On Nov 29, 2007, at 5:12 PM, James Bucanek wrote:
A helper is given a name that includes its user and a job number. So it would register a port with a name like "QRecallHelper.501.6f3b21e0".
So then let me ask why you think that name has been registered in the root bootstrap when it doesn't appear in the following output?
I guess I wasn't clear. Since the registration isn't throwing any errors, I'm assuming that the helper is registering its name in *some* bootstrap. I expected that to be the same bootstrap as the parent process that launched it, but it's clearly not. Would it help to know the parent of the scheduler daemon? I could add debug code to log the PPID of each process as it starts up.
echo 'per-user namespace'; launchctl bslist | fgrep -i qre echo 'root namespace'; sudo launchctl bslist | fgrep -i qre
per-user namespace A QRecallMonitor
root namespace A QRecallScheduler.501
As you've indicated NSConnection's registerName is succeeding, we can probably assume that the name is being registered in _some_ bootstrap, but some subtlety of your NSTask approach may be landing it in a bootstrap that you don't expect.
The helper is either a normal executable or a SUID root executable (a la MoreAuthSample) that gets launched with: + (NSTask*)launchHelper:(NSString*)helperPath withCommand:(NSString*)commandName passingAuthorization:(AuthorizationRef)authorizationRef returningPortName:(NSString**)portNamePtr { NSTask* helperTask = [[NSTask new] autorelease]; NSString* portName = nil; NS_DURING // If a helper wasn't specified, use the bundled helper if (helperPath==nil) helperPath = [[NSBundle mainBundle] pathForResource:kHelperName ofType:nil]; // Prepare the helper to execute [helperTask setLaunchPath:helperPath]; // Redirect the task's stdin and stdout to these NSPipe objects, so we can talk to the task NSPipe* inPipe = [NSPipe pipe]; NSPipe* outPipe = [NSPipe pipe]; [helperTask setStandardInput:inPipe]; [helperTask setStandardOutput:outPipe]; NSFileHandle* stdInHandle = [inPipe fileHandleForWriting]; NSFileHandle* stdOutHandle = [outPipe fileHandleForReading]; // Start the task running [helperTask launch]; ... Followed by a bunch of convoluted code to passes all of the startup parameters to the helper via stdin (which the helper does get, because those get logged as the helper starts up). My assumption was that [NSTask launch] would start the process in the same environment/session/bootstrap as the parent process but something seems to be interfering with that. I can see a couple of possible workarounds: - Figure out why the helper's ports aren't getting registered in a namespace that's accessible by its parent. Maybe I need to use something other than NSTask to start the child process. - Return (once again!) to using UNIX domain sockets for communications, which don't have these kinds of scoping issues. -- James Bucanek