Re: Dumping input to NSTask
Re: Dumping input to NSTask
- Subject: Re: Dumping input to NSTask
- From: "Louis C. Sacha" <email@hidden>
- Date: Thu, 15 Jul 2004 04:12:14 -0700
Hello...
After messing around with this a bit, I discovered that I was wrong
about NSTask automatically closing the write end of the pipe used as
the standard input for the task when the task is launched, so you
don't need to write all of the input data to the pipe before
launching the task. I'm not really sure how that got stuck in my
head, but it didn't make sense once I stopped to think through how
things would have to work (and would be a really bad idea if the
input data size was more than the pipe buffer size).
I'm pretty sure that the reason you are having problems with the
particular executable you are running with NSTask is that it reads
data until it recieves the endOfData signal, which never happens
because the file descriptor is not closed.
I hope that there is a better way to accomplish it, but one (very
unsupported) workaround would be to do this after you finish writing
all of your data to the standard input pipe:
(you will need to #include "unistd.h")
NSFileHandle *input = [[yourTask standardInput] fileHandleForWriting];
close([input fileDescriptor]);
[input setValue:[NSNumber numberWithUnsignedShort:1] forKey:@"_flags"];
This manually closes the fileDescriptor of the NSFileHandle, and then
changes the flag that NSFileHandle uses to determine if it is
supposed to close the file descriptor when the NSConcreteFileHandle
instance is dealloc'ed.
I don't know if doing this has any negative effects on any of the
other objects involved, and it relies on the internal implementation
details of a private concrete subclass, so I wouldn't rely on it
continuing to work in the future. If creating a temporary file is an
acceptable option, that might be a better way to go.
And here's the fixed version of my little summary of running a task:
1) Create the instance of NSTask used for running the task, and set
the basic things like path, arguments, etc...
2) Create input and output pipes if you need to send input or get
output, and use the NSTask setInput: and setOutput: instance methods
so that they will be connected to your task.
**3) Launch the task.
**4) If you need to send input get the NSFileHandle from the NSPipe
for the input, and write the data to it.
**4b) ...(optionally, close the file descriptor if the tool requires it)...
5) Wait until the task finishes or check for available data using a
timer or the notifications, and get your output from the output
pipes's NSFileHandle. If the size of the output is more than the pipe
buffer size (8k ?) you will need to keep checking / reading the
available data to make space in the buffer.
6) When the task is finished, you can check the result code from the
tool using the terminationStatus instance method, but you need to be
sure the task is actually done (using isRunning if you didn't use
waitUntilExit) before you call it.
Hope that helps,
Louis
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.