I would say that your "...IgnoringErrors" methods are masking a real problem, 
and you shouldn't have written them let alone used them.  (By the way, you 
didn't post them except incidentally in your screenshot.)

The exception is saying that the file descriptor backing the 
NSPipe/NSFileHandle has been closed.  Retrying after some time can only result 
in the frameworks co-opting a new, unrelated file object that happened to get 
the same file descriptor.  That would explain why your reads sometimes never 
get any data -- you're reading from a completely different file object.

I'm not sure why the file descriptor is being closed.  It may be a framework 
bug having to do with garbage collection.

I'd try creating the file descriptors manually with the pipe(2) system call.  
Then, construct NSFileHandles from them with -initWithFileDescriptor:theReadFD 
closeOnDealloc:NO.  (Pass [NSFileHandle fileHandleWithNullDevice] to 
-setStandardInput:, while you're at it.)  After you launch the task, be sure to 
close the write ends of your pipes.  And, of course, when everything is 
finished up, close the read ends, too.

By the way, there's nothing incorrect about getting the task-terminated 
notification before the end-of-file for the task output or error file handles.  
There's no guarantee about the order of those events.

On Mar 17, 2011, at 4:01 AM, Jason Harris wrote:

> - (BOOL) waitTillFinished
> {
>    // wait for task to exit:
>    while (![self shouldFinishUp])
>    {
>        // If the task is terminated we should set up a pending termination 
> which will terminate in a bit. This catches some
>        // zombie NSTasks where either the outputData or errorData of 0 were 
> never posted..
>        BOOL terminated = ![task_ isRunning];
>        if (terminated && !pendingTermination_)
>        {
>            DebugLog(@"...Found terminated for %@ ...", [self 
> commandLineString]);
>            [self setPendingTermination];
>        }
> 
>        BOOL runLoopRan = [[NSRunLoop currentRunLoop] 
> runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
>        if (!runLoopRan)
>            break;
>        if (!isFinished_)
>            DebugLog(@"...waitTillFinished still waiting for %@ ...", [self 
> commandLineString]);
>    }
> 
>    [self finishUp];
>    DebugLog(@"...Exiting waitTillFinished for %@ ...", [self 
> commandLineString]);
>    return (result_ == 0);
> }
> 
> 
> + (ExecutionResult*) execute:(NSString*)cmd withArgs:(NSArray*)args 
> onTask:(NSTask*)task
> {
>    ShellTask* shellTask = [[ShellTask alloc] initWithCommand:cmd andArgs:args 
> onTask:task];
> 
>    [shellTask->task_ launch];            // Start the process
>    DebugLog(@"launched %@", [shellTask commandLineString]);
> 
>    [shellTask waitTillFinished];
> 
>    DebugLog(@"Finished execute cmd for %@", [shellTask commandLineString]);
> 
>    NSString* outStr = [[NSString alloc] initWithData:shellTask->outputData_ 
> encoding:NSUTF8StringEncoding];
>    NSString* errStr = [[NSString alloc] initWithData:shellTask->errorData_  
> encoding:NSUTF8StringEncoding];
>    ExecutionResult* result = [ExecutionResult resultWithCmd:cmd args:args 
> result:shellTask->result_ outStr:outStr errStr:errStr];
>    result->theShellTask_ = shellTask;
>    return result;
> }

> BAD:
> --------
> 0x1014810/-[MacHgDocument initializeRepositoryData] Initializing log entry 
> collection
> 0x1250100/+[ShellTask execute:withArgs:onTask:]    launched localhg 
> combinedinfo --cwd /Volumes/QuickSilver/Development/sandbox/RhodeCode
> 0x1250100/-[ShellTask gotExit:]                    ...got Exit for localhg 
> combinedinfo --cwd /Volumes/QuickSilver/Development/sandbox/RhodeCode ...
> 0x1250100/-[ShellTask gotError:]                   ...got NULL Error Output 
> for localhg combinedinfo --cwd 
> /Volumes/QuickSilver/Development/sandbox/RhodeCode ...
> 0x1250100/-[ShellTask waitTillFinished]            ...waitTillFinished still 
> waiting for localhg combinedinfo --cwd 
> /Volumes/QuickSilver/Development/sandbox/RhodeCode ...
> 0x1250100/-[ShellTask finishUp]                    ...Finishing up for 
> localhg combinedinfo --cwd /Volumes/QuickSilver/Development/sandbox/RhodeCode 
> ...

> Now a couple things to note is that if the   [self 
> performSelector:@selector(finishUp)  withObject:nil  afterDelay:10.0]    
> fires in the BAD case then the outer call to waitTillFinished just sort of 
> vanishes, since there is always a DebugLog call which prints "...Exiting 
> waitTillFinished for ..." but is can be seen in the BAD transcript this just 
> isn't present.

I see no evidence that it has "vanished".  It seems to me that 
-waitTillFinished is still executing, presumably blocked in the run loop.  Note 
that, not only is the DebugLog at the end of -waitTillFinished not hit, but 
neither is the one immediately after the call to it in 
+execute:withArgs:onTask:.  In other words, it just hasn't returned.

Good luck,
Ken

_______________________________________________

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 arch...@mail-archive.com

Reply via email to