[launchd-dev] launchctl unload not working
James Bucanek
subscriber at gloaming.com
Thu Nov 29 21:37:21 PST 2007
Kevin Van Vechten <mailto:kvv at 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
More information about the launchd-dev
mailing list