Re: hung in read$UNIX2003
Re: hung in read$UNIX2003
- Subject: Re: hung in read$UNIX2003
- From: Michael Ash <email@hidden>
- Date: Sat, 4 Apr 2009 00:20:48 -0400
On Fri, Apr 3, 2009 at 2:42 PM, Ken Thomases <email@hidden> wrote:
> On Apr 3, 2009, at 11:10 AM, Michael Ash wrote:
>
>> On Fri, Apr 3, 2009 at 9:36 AM, Michael Domino
>> <email@hidden> wrote:
>>
>>> I have a task prepared and launched with the code below, and when it
>>> returns
>>> (in this situation that status code returned from terminationStatus is
>>> 0),
>>> it hangs in availableData, never to return. [...]
>>>
>>> messagePipeError = [NSPipe pipe];
>>> messagePipeOutput = [NSPipe pipe];
>>> [task setLaunchPath:@"/usr/bin/hdiutil"];
>>> [task setArguments:[NSArray
>>> arrayWithObjects:@"info", nil]];
>>> [task setStandardError:messagePipeError];
>>>
>>> [task setStandardOutput:messagePipeOutput];
>>>
>>> [task launch];
>>> [task waitUntilExit];
>>> status = [task terminationStatus];
>>>
>>> NSData *messageDataError = [[messagePipeError
>>> fileHandleForReading] availableData];
>>> messageError = [[[NSString alloc]
>>> initWithData:messageDataError encoding:NSUTF8StringEncoding]
>>> autorelease];
>>
>> I don't know if this is the cause of your problem or not, but never,
>> ever do this. Don't call waitUntilExit before you read. Pipes have a
>> small buffer (4kB?) and if it fills up then further writes will block.
>> This means that if you do a waitUntilExit while the subprocess is
>> writing more data than the pipe can buffer, you'll deadlock. The
>> subprocess will be waiting for you to read data before it can
>> continue, and you will be waiting for it to exit before you read data.
>> Read all data (using readDataToEndOfFile or equivalent) *before* you
>> do waitUntilExit.
>
> And, since you have two pipes, you're going to have to read from both
> simultaneously. Otherwise, you still have a chance for deadlock, if you're
> blocking reading on one handle while the subprocess is blocking waiting for
> the other pipe to be drained.
>
> This is best done using the asynchronous methods of NSFileHandle.
An excellent point. I missed that particular feature of his code.
Personally, for a situation like this, where the subprocess is
expected to finish its work quickly, I would just write a little loop
calling select() and read() to drain both pipes at the same time. But
the important thing is just to read the data out of the pipes without
blocking on anything else or without blocking on either pipe
individually. How you do that is pretty much just a matter of taste,
or of what fits your code best.
Mike
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden