On Mar 18, 2011, at 11:07 PM, Ken Thomases wrote: > 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.)
(Ahh yep. I didn't want to spam the group with lots and lots of code and headers and other bits. I tried to pick the "relevant" code and then provided the link to the sourcefiles on bitbucket...) And in answer to this I was grasping at straws and I didn't really write this code, I was trying this since it was recommended in some previous posts by others (I can post the references if you are interested). In the end I think this @try @catch just served to not crash the app and return nil for the result... But you are right I am keenly interested in what is going wrong and how to remedy it. (As I said previously the error would manifest itself every so often which was of course very annoying, but now moving to the Moriarty style of things, the errors suddenly became quite noticeable.) > 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 am sorry, but can you explain the paragraph in more detail? (Just to be clear sometimes I never get the exception and yet it still drops data... So the ugly bit of the @catch is never hit but it still was dropping the data...) > 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. Sorry just so I don't stuff this up can I ask you to give me the exact code here... or point me to an example of this? > (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. I'd like to try this thanks! > 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. Yes, I gathered that. I also gathered that you should always get all three things right? ie (i) The NSTaskDidTerminateNotification (ii) and the NULL for the NSFileHandleReadCompletionNotification for stdOut (iii) and the NULL for the NSFileHandleReadCompletionNotification for stdErr Well when it was dropping the data I was missing one of these notifications and my empirical observation was that more commonly I was receiving the NSTaskDidTerminateNotification first and then either of the other notifications. Whereas when things were working it was uncommon or I didn't get the NSTaskDidTerminateNotification first.... It was just a data point I was trying to give everyone so it might shed some light on the problem. > 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. Ahh so you are saying that the loop is still executing? Well if I put a break point in the loop in waitTillFinished then it doesn't break on this breakpoint... Maybe this is an XCode bug or something? Also I would imagine though if this were the case then stepping up through the call stack would have been normal. Ie would have got back to the loop. Instead it was like I hit continue when I reached __CFRunLoopRun... Thanks for the comments though! Cheers, Jas_______________________________________________ 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