Re: Does waitUntilExit really mean that?
Re: Does waitUntilExit really mean that?
- Subject: Re: Does waitUntilExit really mean that?
- From: Michael Domino <email@hidden>
- Date: Sat, 11 Apr 2009 14:29:46 -0400
Ken,
I ended up throwing out NSTask in favor of popen for running hdiutil,
and my code seems much more stable now. Did I shoot myself in the foot
some other way? I'm executing this in a pthread of its own. I also
kept getting exceptions thrown for nil arguments to NSConreteTask,
besides the problems getting the standard output either partially or
not at all. This seems better:
FILE *instream = popen(cmdbuf, "r");
if(instream) {
// read the output, one line at a time.
string data;
int MAX_BUFFER = 512;
char buffer[MAX_BUFFER];
while (!feof(instream)){
if (fgets(buffer, MAX_BUFFER, instream) != NULL){
data.append(buffer);
}
}
// close the pipe.
status = pclose(instream);
-Michael
On Apr 8, 2009, at 5:11 PM, Michael Domino wrote:
Ken,
After all the discussion and hours of fun trying the various code
permutations, this is the only thing that works reliably for me:
[task launch];
NSData* outData;
NSString* messageOutput = [[NSString new] autorelease];
while ((outData=[readHandleOutput availableData]) && ([outData
length])) {
NSString* theString=[[NSString alloc] initWithData:outData
encoding:NSUTF8StringEncoding];
messageOutput = [messageOutput stringByAppendingString:theString];
[theString release];
}
[task waitUntilExit];
Using the notification methods, I often ended up with an empty or
partial output string. This is running in a thread of its own, by
the way, so there are no blocking issues with the main thread.
Thanks again,
Michael
On Apr 8, 2009, at 11:13 AM, Ken Thomases wrote:
On Apr 7, 2009, at 10:44 AM, Michael Domino wrote:
Thanks very much for the reply.
You're welcome.
I have two methods to handle the notifications for the error and
output pipes (see below). Since we are supposed to be reading to
EOF, do I really need to call readToEndOfFileInBackgroundAndNotify
at the end of each call?
No, you should not. The other asynchronous methods of NSFileHandle
require that you re-issue the call during the notification handler
if you want to keep reading/writing, but that's not necessary or
desirable when reading to EOF.
To answer your question, after the code runs I get my error and
output strings and parse them. If waitUntilExit is not going to
wait long enough for the i/o process to complete, how would I go
about ensuring that the run loop is run until both NSFileHandles
have sent their notifications?
You'd use a loop something like this:
while (![msgTarget isEverythingCompleted])
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
In your notification handlers, you'd set the "everything completed"
flag after both file handles had reached EOF. -runMode:beforeDate:
returns after each input source fires, thus allowing the check of
the flag. (I repeat, just because it's an area that's prone to
confusion: the sending of a notification doesn't have anything to
do with the run loop, but in this case, where external resources/
events are being monitored, the sending of the notification is
happening because a run loop input source has fired.)
Use NSTaskDidTerminateNotification instead of or in addition to
waitUntilExit?
That doesn't help. It's still the case that task termination may
be detected before the file handles detect EOF.
You may, if you like, use a loop like the above in combination with
NSTaskDidTerminateNotification instead of -waitUntilExit. In that
case, the "everything completed" flag should be set after all three
notifications have been received. Doesn't seem simpler to me, but
I guess it's more symmetrical.
Is there some reason this has to be on a background thread? If it
were on the main thread, where you can rely on the run loop
running, you could just set everything in motion and then handle
all of the results in the notification handlers without having to
bother with managing how long you run the run loop. MsgTarget
would just keep track of which things had completed (each of the
two file handles and the task itself). Inside whichever handler
completed the last of those, just invoke the next step (processing
the task results).
Although checking the task termination status is good practice, if
you don't really need that information or act on it, you can just
not bother observing NSTaskDidTerminateNotification. If you do
need the termination status, then you have to keep the NSTask
retained until NSTaskDidTerminateNotification or you won't receive
it or be able to check the status.
Regards,
Ken
Michael Domino
email@hidden
Michael Domino
email@hidden
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
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