views:

348

answers:

4

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.

+1  A: 

It looks like you're missing a

[proc setStandardOutput:output];
kubi
I added that line but now it seems like I get no output at all.
macatomy
A: 

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

Peter Hosey
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
macatomy
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
macatomy
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
Thanks for the correction :) Do you have any ideas what else could be wrong?
macatomy
A: 

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
+1  A: 

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 :)

macatomy