Re: NSTask/NSPipe STDIN hangs on large data, sometimes...
Re: NSTask/NSPipe STDIN hangs on large data, sometimes...
- Subject: Re: NSTask/NSPipe STDIN hangs on large data, sometimes...
- From: Bill Bumgarner <email@hidden>
- Date: Fri, 17 Jan 2003 11:25:35 -0500
On Thursday, Jan 16, 2003, at 21:11 US/Eastern,
email@hidden wrote:
Has anyone else experienced this problem and solved it or am I a lone
corner
case? I googled a little and have looked at some of the Cocoa sites
(and
this list), but nothing jumped out at me that was addressing or
solving this
issue.
Is this a problem with my code (I'll post a spike of the app if
needed) or
the frameworks or Darwin, OR?
Are you using the 'readInBackgroundAndNotify' mode on NSFileHandle? If
not, that is the cause of your problem as the buffering in NSFileHandle
will end up blocking on itself. This isn't so much a bug as fallout
from the way the system works (and one for which an easy workaround
exists -- readInBackgroundAndNotify).
Also, availableData, readDataToEndOfFile, and-- I think--
readDataOfLength: can all cause the NSFileHandle instance to block
without readInBackgroundAndNotify having been activated.
You can do non-blocking I/O without -readInBackgroundAndNotify. An
example that works across Windows, OS X, and Solaris (yes, the code is
old -- still works, though you will need to rip out some stuff):
// platform specific low-level I/O
#ifdef WIN32
#import <System/windows.h>
#elif defined(__MACH__)
#import <bsd/libc.h>
#elif defined(__svr4__)
#import <unistd.h>
#import <sys/filio.h>
#endif
// import APIs to NeXT provided frameworks
#import <Foundation/Foundation.h>
// import local framework's API
#import "CFBFoundation.h"
// import API required througout this file's scope
#import "NSFileHandle_CFBNonBlockingIO.h"
@implementation NSFileHandle (CFBNonBlockingIO)
/*"
* Adds non-blocking I/O API to NSFileHandle.
"*/
- (NSData *)availableDataNonBlocking;
/*"
* Returns an NSData object containing all of the currently
available data. Does not block if there is no data; returns nil
* instead.
"*/
{
return [self readDataOfLengthNonBlocking: UINT_MAX];
}
- (NSData *)readDataToEndOfFileNonBlocking;
/*"
* Returns an NSData object containing all of the currently
available data. Does not block if there is no data; returns nil
* instead. Cover for #{-availableDataNonBlocking}.
"*/
{
return [self readDataOfLengthNonBlocking: UINT_MAX];
}
- (unsigned int) _availableByteCountNonBlocking
{
#ifdef WIN32
HANDLE nativeHandle = [self nativeHandle];
DWORD lpTotalBytesAvail;
BOOL peekSuccess;
peekSuccess = PeekNamedPipe(nativeHandle, NULL, 0L, NULL,
&lpTotalBytesAvail, NULL);
if (peekSuccess == NO)
[NSException raise: NSFileHandleOperationException
format: @"PeekNamedPipe() NT Err # %d",
GetLastError()];
return lpTotalBytesAvail;
#elif defined(__MACH__) || defined(__svr4__)
int numBytes;
int fd = [self fileDescriptor];
if(ioctl(fd, FIONREAD, (char *) &numBytes) == -1)
[NSException raise: NSFileHandleOperationException
format: @"ioctl() Err # %d", errno];
return numBytes;
#else
#warning Non-blocking I/O not supported on this platform....
abort();
return nil;
#endif
}
- (NSData *)readDataOfLengthNonBlocking:(unsigned int)length;
/*"
* Reads up to length bytes of data from the file handle. If no
data is available, returns nil. Does not block.
"*/
{
unsigned int readLength;
readLength = [self _availableByteCountNonBlocking];
readLength = (readLength < length) ? readLength : length;
if (readLength == 0)
return nil;
return [self readDataOfLength: readLength];
}
@end
_______________________________________________
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.