Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a crash in NSTask

Tags:

macos

cocoa

I've had a report from the field of a crash at -launch on NSTask.

The code in question is:

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/zsh"];
if(ignore)
{
    [task setArguments:@[scriptPath, recordingFolder, Argument]];
}
else
{
    [task setArguments:@[scriptPath, recordingFolder]];
}

NSPipe *outPipe = [NSPipe pipe];
[task setStandardOutput:outPipe];

NSPipe *errorPipe = [NSPipe pipe];
[task setStandardError:errorPipe];

[task launch];

The scriptPath is a script that is included in the app bundle. The crash says:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Failed to set posix_spawn_file_actions for fd -1 at index 0 with errno 9'

What could be the cause of this? What file descriptor do the posix_spawn_file_actions refer to? Does it mean that the executable script is wrong or that the outPipe or errPipe are not well formed?

I believe it is referring to the posix_spawn function: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/posix_spawn.2.html

And errno 9 is EBADF (bad file number).

like image 855
George Avatar asked Aug 18 '14 19:08

George


3 Answers

I've got a similar error , after I use below command, it's OK, you can try it.

NSFileHandle *file=[outPipe fileHandleForReading];
[task launch];
....//read file.
//this is the most important.
[file closeFile];
like image 53
user5184672 Avatar answered Nov 16 '22 14:11

user5184672


If you are calling this code many different times sequentially, you are running out of file descriptors -- you need to close the pipes after you are done. The correct way to do it is to deallocate NSTask and it will close the file channels. Put the NSTask-related code in an autoreleasepool statement:

@autoreleasepool {
  NSTask* task = [NSTask new];
  ...
  [task launch];
  ...
  [task waitUntilDone];
}
like image 32
Anton Avatar answered Nov 16 '22 14:11

Anton


For the issue in the question, I suggest that we should put the code of CreateProcess() in an @autoreleasepool block as Apple's doc shows that we should not send -[closeFile] to fileHandleForReading explicitly.

https://developer.apple.com/reference/foundation/nspipe/1414352-filehandleforreading?language=objc

Declaration

@property(readonly, retain) NSFileHandle *fileHandleForReading;

Discussion

The descriptor represented by this object is deleted, and the object itself is automatically deallocated when the receiver is deallocated.

You use the returned file handle to read from the pipe using NSFileHandle's read methods—availableData, readDataToEndOfFile, and readDataOfLength:.

You don’t need to send closeFile to this object or explicitly release the object after you have finished using it.

like image 34
Tai Ly Avatar answered Nov 16 '22 13:11

Tai Ly