Exception `-[NSConcreteFileHandle readDataOfLength:]: Bad file descriptor` when running a NSUserUnixTask

StackOverflow https://stackoverflow.com/questions/16637501

  •  29-05-2022
  •  | 
  •  

Domanda

I'm using NSUserUnixTask to run an unsandboxed NSTask on my sandboxed app. However, my code hangs on calls to [NSFileHandle readDataToEndOfFile]. If I remove those calls it works perfectly. If I replace [NSFileHandle readDataToEndOfFile] with [NSFileHandle availableData] it hangs as well.

Here is the code:

NSUserUnixTask* unixTask = [[NSUserUnixTask alloc] initWithURL: [NSURL fileURLWithPath: path] error: nil];

// Create error file handle
NSFileHandle* errorFH = [NSFileHandle fileHandleWithStandardError];
[unixTask setStandardError: errorFH];

// Create output file handle
NSFileHandle* outputFH = [NSFileHandle fileHandleWithStandardOutput];
[unixTask setStandardOutput: outputFH];

// Run task with termination handler
[unixTask executeWithArguments: nil completionHandler: ^(NSError* error2) {

    // Save output
    NSString* output = [[NSString alloc] initWithData: [outputFH readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    if ([output length]) { // <-- Execution never reaches this line when the block is called
        NSLog(@"%@", output);
    }

    // Read error 1
    NSString* error1 = [[NSString alloc] initWithData: [errorFH readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    if ([error1 length]) {
        NSLog(@"%@", error1);
    }

    // Read error 2
    if (error2) {
        NSLog(@"%@", error2);
    }
}];

Nothing is logged on Xcode's console, but if I open Console.app I see this line:

Warning: Exception caught during decoding of received reply to message 'executeScript:interpreter:arguments:standardInput:standardOutput:standardError::', dropping incoming message and calling failure block.

Exception: *** -[NSConcreteFileHandle readDataOfLength:]: Bad file descriptor

Hmmm, how can I solve this? Before I had my app sandboxed I used NSPipe in conjunction with NSTask and everything worked, but now NSUserUnixTask requires the use of NSFileHandle instead and I reckon my problem is simply because I'm not using it correctly. But still I have no idea what I'm doing wrong.

È stato utile?

Soluzione

It seems to me that you have to use NSPipe to read stderr and stdout from NSUserUnixTask in the same way it is done with NSTask.

I have tested it with a "/bin/ls" task and it produced the expected output:

NSPipe *outPipe = [NSPipe pipe];
NSPipe *errPipe = [NSPipe pipe];
NSString *path = @"/bin/ls";
NSUserUnixTask *unixTask = [[NSUserUnixTask alloc] initWithURL: [NSURL fileURLWithPath: path] error: nil];
[unixTask setStandardOutput:[outPipe fileHandleForWriting]];
[unixTask setStandardError:[errPipe fileHandleForWriting]];
[unixTask executeWithArguments:nil completionHandler:^(NSError *error) {
    NSString *output = [[NSString alloc] initWithData: [[outPipe fileHandleForReading] readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    NSLog(@"stdout: %@", output);

    NSString *error1 = [[NSString alloc] initWithData: [[errPipe fileHandleForReading] readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    NSLog(@"stderr: %@", error1);
}];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top