trying to control the output of a subprocess.
trying to control the output of a subprocess.
- Subject: trying to control the output of a subprocess.
- From: Paul Archibald <email@hidden>
- Date: Wed, 3 Sep 2008 19:53:49 -0700
Hey folks,
MyApp is a GUI to a command line program (CLP) to which I do not have
the source code. MyApp asks the user to select a directory, makes a
list of the files in that directory, and calls the CLP for each file.
The CLP processes the file(s), reporting its progress to the console
with a message like "filename : block 2 finished" until it is
finished "filename : finished." I use that output to inform the
progressbars and other elements of my GUI.
Well, it worked fine up until now, when I am doing some testing and
am launching MyApp from the Finder instead of from Xcode. Now, the
progress output is being buffered until the CPL is finished with the
file, and then spewing out the entire buffer (which MyApp has been
intercepting). This is abd for me since I need that line by line output.
I have seen some posts on the Cocoa and Xcode lists that mention
similar problems, but I can't find one that explains how to fix it. I
am using the TaskWrapper class from the Moriarity sample to execute
my tasks. Here is how TaksWrapper sets up the NSTask that it uses:
////////
- (void) startProcess {
// We first let the controller know that we are starting
[controller processStarted:self];
task = [[NSTask alloc] init];
// The output of stdout and stderr is sent to a pipe so that we
can catch it later
// and send it along to the controller; notice that we don't
bother to do anything with stdin,
// so this class isn't as useful for a task that you need to
send info to, not just receive.
[task setStandardOutput: [NSPipe pipe]];
[task setStandardError: [task standardOutput]];
// The path to the binary is the first argument that was passed in
[task setLaunchPath: [arguments objectAtIndex:0]];
// The rest of the task arguments are just grabbed from the array
[task setArguments: [arguments subarrayWithRange: NSMakeRange
(1, ([arguments count] - 1))]];
// Here we register as an observer of the
NSFileHandleReadCompletionNotification, which lets
// us know when there is data waiting for us to grab it in the
task's file handle (the pipe
// to which we connected stdout and stderr above). -getData:
will be called when there
// is data waiting. The reason we need to do this is because if
the file handle gets
// filled up, the task will block waiting to send data and we'll
never get anywhere.
// So we have to keep reading data from the file handle as we go.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData:)
name: NSFileHandleReadCompletionNotification
object: [[task standardOutput] fileHandleForReading]];
// We tell the file handle to go ahead and read in the background
asynchronously, and notify
// us via the callback registered above when we signed up as an
observer. The file handle will
// send a NSFileHandleReadCompletionNotification when it has
data that is available.
[[[task standardOutput] fileHandleForReading]
readInBackgroundAndNotify];
// launch the task asynchronously
[task launch];
// some stuff I added just to see what is going on
int pid = [task processIdentifier];
NSLog(@"pid == %d", pid); // this worked
NSLog(@"tty == %s", ttyname(pid)); // result is (null)
}
/////////
So, does anyone know what to do to fix this? Is it the way the
notifier is getting set up? Something about the file handles or the
pipe that could be set up differently? It seems as though what I want
is control the buffering of the standard output, but I don't know how.
Any ideas?
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden