1

Hi I have the following code:

- (IBAction)runTask:(id)sender {
    NSTask *proc;
    NSPipe *output;
    NSData *data;
    NSString *buffer;

    proc = [[NSTask alloc] init];
    output = [[NSPipe alloc] init];

    [proc setLaunchPath:@"/bin/sh"];
    [proc setArguments:[NSArray arrayWithObjects: @"-c", @"/usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/awk 'NR>1{print $1}' | /usr/bin/sed -e '/@executable_path/d' -e 's/(.*)$//' -e  's/\\/Versions.*$//'", nil]];
    [proc launch];

    data = [[output fileHandleForReading] readDataToEndOfFile];
    buffer = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    NSLog(@"got: %@", buffer);

     // Release
     [proc release];
     [output release];
     [buffer release];
     [data release];
}

The codes purpose is kinda complicated, it uses otool to get a list of the shared libraries used by a binary then it uses sed and awk to filter it into a machine readable format. Just to test I've used the Mac OS X TextEdit.app's binary.

The issue is that the code runs and returns an output but then freezes the app. I went through it line by line and found this line to be the problem:

data = [[output fileHandleForReading] readDataToEndOfFile];

This line itself is logging the output to the console and then freezing the app. I checked this by deleting all other lines after that line, and it still logs the output and freezes. There is nothing in debugger and any suggestions on how to solve this problem would be greatly appreciated.

indragie
  • 18,002
  • 16
  • 95
  • 164
  • 1
    I copied the code into a command-line tool, added the missing `setStandardOutput:` message, and ran it. It works fine, except that you over-release `data` at the end. – Peter Hosey Aug 09 '09 at 05:34
  • “I checked this by deleting all other lines after that line…” I suggest sampling your app instead. See man 1 sample. – Peter Hosey Aug 09 '09 at 06:40

4 Answers4

2

It looks like you're missing a

[proc setStandardOutput:output];
kubi
  • 48,104
  • 19
  • 94
  • 118
1

The solution to this problem was simple,

Its a known bug that after NSTask is executed all logging does not work. It is returning an output, its just not logging it. The solution was to add this line:

[task setStandardInput:[NSPipe pipe]];

And everything works fine :)

aleroot
  • 71,077
  • 30
  • 176
  • 213
indragie
  • 18,002
  • 16
  • 95
  • 164
0

You have an extra slash at the end of the last sed statement. Once you remove it, the script works fine.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • I'm not sure if I removed the right slash, I took out one at the very end of the last sed statement, the line looks like this now [proc setArguments:[NSArray arrayWithObjects: @"-c", @"/usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/awk 'NR>1{print $1}' | /usr/bin/sed -e '/@executable_path/d' -e 's/(.*)$//' -e 's/\\/Versions.*$/'", nil]]; But I get this error: sed: 1: "s/\/Versions.*$/\n": unescaped newline inside substitute pattern – indragie Aug 09 '09 at 02:36
  • Oh and also, I don't think its an issue with the command itself, I tried a very simple "ls /Volumes" and the same thing happens, the output is returned but the app freezes. I added in the setStandardOutput line as suggested by the previous poster, and while that solves the freezing issue, there is no longer any output. Thanks – indragie Aug 09 '09 at 02:39
  • PCWiz: Ah, I forgot to unescape the backslashes before trying the command, and didn't actually read it to see where the last pattern was supposed to end. That last slash does belong there. Sorry. – Peter Hosey Aug 09 '09 at 02:59
  • Thanks for the correction :) Do you have any ideas what else could be wrong? – indragie Aug 09 '09 at 03:02
0

output should be created with [NSPipe pipe] (unowned) and then output should be set as the standard output with [proc setStandardOutput: output]

But the reason you are crashing is because you are releasing data which you did not alloc, new or copy. See the memory management rules.

Also, see Quickies for NSTask for a nice clean implementation of this code.

Peter N Lewis
  • 17,664
  • 2
  • 43
  • 56