NSTask setStandardOutput bug?

  • I have a problem with running this code more than 248 times.
    It is a simplified version of my implementation which is based on an
    example from cocoaDevCentral
    http://cocoadevcentral.com/articles/000031.php

    this is a loop for the sake of demonstrating the problem:

    int l;
    for(l=0; l< 250; l++){
      NSLog(@"%d", l);

      NSTask *ps=[[NSTask alloc] init];
      NSPipe *pipe=[[NSPipe alloc] init];
      NSFileHandle *handle;

      [ps setLaunchPath:@"/bin/ps"];
      [ps setArguments:[NSArray arrayWithObjects:@"-p", PID, @"-o" ,
    @"pcpu", nil]];
      [ps setStandardOutput:pipe];
      handle=[pipe fileHandleForReading];
      [ps launch];
      NSString *string = [[NSString alloc] initWithData:[handle
    readDataToEndOfFile] encoding:NSASCIIStringEncoding];

      NSLog(string);

      [ps release];
      [pipe release];
    }

    where 'PID' is any valid process ID.

    it invariably fails after the 248th iteration with the error:
    [NSCFDictionary setObject:forKey:]: attempt to insert nil value
    I narrowed the crash down to the setStandardOutput call.

    I can only guess it is some kind of memory management issue but can't
    see how.
    if I comment out the '[ps launch]' line (and the two after it) it
    does exactly 124 iterations before crashing.
    any ideas?
  • Wrap the body of this loop with an autorelease pool and see if this
    makes the problem go away.
    You're not autoreleasing anything, but Cocoa may internally have
    performed the equivalent of [[someObject retain] autorelease].
    Also, you are leaking "string".

    justin webster wrote:
    > I have a problem with running this code more than 248 times.
    > It is a simplified version of my implementation which is based on an
    > example from cocoaDevCentral
    > http://cocoadevcentral.com/articles/000031.php
    >
    > this is a loop for the sake of demonstrating the problem:
    >
    > int l;
    > for(l=0; l< 250; l++){
    > NSLog(@"%d", l);
    >
    > NSTask *ps=[[NSTask alloc] init];
    > NSPipe *pipe=[[NSPipe alloc] init];
    > NSFileHandle *handle;
    >
    > [ps setLaunchPath:@"/bin/ps"];
    > [ps setArguments:[NSArray arrayWithObjects:@"-p", PID, @"-o" ,
    > @"pcpu", nil]];
    > [ps setStandardOutput:pipe];
    > handle=[pipe fileHandleForReading];
    > [ps launch];
    > NSString *string = [[NSString alloc] initWithData:[handle
    > readDataToEndOfFile] encoding:NSASCIIStringEncoding];
    >
    > NSLog(string);
    >
    > [ps release];
    > [pipe release];
    > }
    >
    > where 'PID' is any valid process ID.
    >
    > it invariably fails after the 248th iteration with the error:
    > [NSCFDictionary setObject:forKey:]: attempt to insert nil value
    > I narrowed the crash down to the setStandardOutput call.
    >
    > I can only guess it is some kind of memory management issue but can't
    > see how.
    > if I comment out the '[ps launch]' line (and the two after it) it does
    > exactly 124 iterations before crashing.
    > any ideas?
  • I believe the underlying problem is that you're exceeding the system
    limit on open file handles.

    But the local autorelease pool that John suggested should fix it.
  • On Dec 20, 2007, at 6:58 PM, Jerry Krinock wrote:

    > I believe the underlying problem is that you're exceeding the system
    > limit on open file handles.
    >
    > But the local autorelease pool that John suggested should fix it.

    It will, or explicitly calling "close" on the NSFileHandle will also
    fix it.

    File descriptors are a scarce resource; while an NSFileHandle will
    close its fd when it's dealloc'd, it's better to close it yourself
    when you know you're done with it.

    .chris

    --
    Chris Parker
    Cocoa Frameworks
    Apple Inc.
  • > Wrap the body of this loop with an autorelease pool and see if this
    > makes the problem go away.
    > You're not autoreleasing anything, but Cocoa may internally have
    > performed the equivalent of [[someObject retain] autorelease].
    > Also, you are leaking "string".

    yeah I thought tried that,
    obviously not correctly,
    works now.
    thanks
previous month december 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Go to today