Re: NSTask, NSPipe's and interactive UNIX command
Re: NSTask, NSPipe's and interactive UNIX command
- Subject: Re: NSTask, NSPipe's and interactive UNIX command
- From: Mike Davis <email@hidden>
- Date: Wed, 2 Jan 2002 16:59:03 -0500
I've had the same problem myself and here's what I suggest...
Use plain old read() on the pipe followed by a select to see if there's
anything else to read. Run it in a different thread, so your app doesn't
block, and use the regular communication mechanisms between two threads
(see NSConnection).
You can kill off the reading thread by closing the pipe from the main
thread - it'll cause an error in read().
Here's my reading code...
- (NSData*)readData:(int)sd
{
int bytesLeft = READ_BUFFER_SIZE;
int totalBytesRead = 0;
struct timeval timeout = { 0, 10 };
NSData *theDataRead = nil;
char *readBuffer;
char *theData;
fd_set readfds, writefds, exceptfds;
int result;
if( ( readBuffer = (char*)malloc( READ_BUFFER_SIZE ) ) == NULL )
return nil;
theData = readBuffer;
while( bytesLeft > 0 ) {
result = read( sd, theData, (unsigned long)bytesLeft );
if( result <= 0 ) break;
bytesLeft -= result;
theData += result;
totalBytesRead += result;
if( bytesLeft == 0 ) break; // Stop the read if we've read them
all in
// Ensure that after reading the first byte we test to see if
there are bytes still to read.
// This makes sure that we don't wait here until all the
required bytes have been read
// as this might be a *really* long time (like forever).
FD_ZERO( &readfds );
FD_ZERO( &writefds );
FD_ZERO( &exceptfds );
FD_SET( sd, &readfds ); // We're only interested in reading bytes
result = select( sd + 1, &readfds, &writefds, &exceptfds,
&timeout );
if( result < 0 ) break;
if( !FD_ISSET( sd, &readfds ) ) break;
}
if( totalBytesRead > 0 ) theDataRead = [NSData
dataWithBytes:readBuffer length:totalBytesRead];
free( (void*)readBuffer );
return theDataRead;
}
On Wednesday, January 2, 2002, at 04:38 PM, cocoa-dev-
email@hidden wrote:
From: "Sven-S. Porst" <email@hidden>
To: "Cocoa-Dev Liste (Apple)" <email@hidden>
Subject: Re: NSTask, NSPipe's and interactive UNIX command
Date: Wed, 2 Jan 2002 22:26:24 +0100
The problem is that notifications of available data on the output pipe
are fired only *after* "command" has exited! That is, the behaviour of
this code is as follows: "command" is run but no output is shown;
This may not be of much help but I currently have a similar problem to
yours and was about to ask a similar question. In my case I call an
application via NSTask that takes a few seconds before giving it's first
output. My setup is pretty much the same as yours. Unfortunately I don't
get notified of this and hence cannot respond to the application's
output.
While playing around with this, I discovered that using my own
application (say, by opening several menus, particularly the services
menu or the menu of a popup-button that is in my window, will eventually
trigger the notification - even before the command line application has
exited.
I am very confused by this behaviour - but then I am very new to the
notifications and stuff, I've basically just followed the documentation
and examples (none of which treat the case of 'interaction' with a
command line application incidentally).
Any hints as to what may be going wrong are greatly appreciated.
Happy new year
Sven
--
Sven-S. Porst . PGP: 0x0085ABA3 . http://homepage.mac.com/ssp
"Science is magic that works."