NSConcreteTask launchWithDictionary crash
Asked Answered
I

1

9

I seem to get a lot of crash reports like this:

Crashed Thread:  14

Exception Type:  EXC_GUARD
Exception Codes: 0x4000000200000000, 0x00007fff96f73c48

Thread 14 Crashed:
0   libsystem_kernel.dylib              0x00007fff97b7213a dup + 10
1   com.apple.Foundation                0x00007fff8a116cee -[NSConcreteTask launchWithDictionary:] + 2457
2   com.mycompany.myapp  0x0000000100022814 +[MCSoftwareUpdate automaticallyCheckForUpdates] + 352
3   com.apple.Foundation                0x00007fff89fed76b __NSThread__main__ + 1318
4   libsystem_pthread.dylib             0x00007fff8d2e4899 _pthread_body + 138
5   libsystem_pthread.dylib             0x00007fff8d2e472a _pthread_start + 137
6   libsystem_pthread.dylib             0x00007fff8d2e8fc9 thread_start + 13

It doesn't just affect the above method - it affects any code that uses NSTask. I did some research and it was suggested that repairing permissions may fix the issue, but that's not very useful because I have no way of getting in contact with the users reporting these crashes. I am already placing the code in a try catch block - is there anything else I can do at my end to minimize or eliminate it?

I wrote the following function to wrap around NSTask.

Code:

+ (BOOL)runTask:(NSString*)taskPath arguments:(NSArray*)args task:(NSTask**)taskObj
{
    if (![[NSFileManager defaultManager] isExecutableFileAtPath:taskPath] || [[NSWorkspace sharedWorkspace] isFilePackageAtPath:taskPath]) { 
        NSLog(@"Error: %@ is not executable",taskPath);
        return NO;
    }

    @try {
        NSTask *task = [[NSTask alloc] init];

        if (taskObj != NULL) *taskObj = task;

        [task setLaunchPath:taskPath];
        if (args) [task setArguments:args];
        [task setStandardError:[NSFileHandle fileHandleWithNullDevice]];
        [task setStandardOutput:[NSFileHandle fileHandleWithNullDevice]];

        [task launch];

        [task waitUntilExit];

        taskObj = nil;
        [task release];

        return YES;
    }

    @catch (NSException *exc) {
        NSLog(@"Exception running task %@: %@",taskPath,[exc reason]);
    }

    return NO;
}
Interplead answered 14/5, 2014 at 23:29 Comment(2)
I'm seeing this in one of my apps, when the system is getting low on file handles. Oddly, only when my apps runs standalone — when i run it for Xcode, it doesn't crash. After a reboot, the issue doesn't persist. Since it's a signal, catching exceptions does no good, so this is a really terrible user experience, not being able to handle this :(.Vashtee
Yes, a customer confirmed to me yesterday that it disappeared for him after a reboot.Interplead
C
1

If rebooting fixes the problem, then it seems that minimizing your file handles may help prevent this issue. But, I would still try to reproduce the issue locally, by creating a lot of file handles without closing them, so that you know for sure what is causing the crash.

I see that you are creating your file handle as you pass it as a parameter. This prevents you from controlling when that file handle is closed. I would instead keep a reference to the file handle, so that you can close it when it is no longer used:

NSFileHandle *errorFileHandle = [NSFileHandle fileHandleWithNullDevice];
[task setStandardError:errorFileHandle];

NSFileHandle *outputFileHandle = [NSFileHandle fileHandleWithNullDevice];
[task setStandardOutput:outputFileHandle];

...
//outputFileHandle is no longer used
[outputFileHandle close];
Critique answered 21/11, 2015 at 22:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.