NSConcreteTask launchWithDictionary崩溃

时间:2014-05-14 23:29:32

标签: objective-c cocoa nstask

我似乎得到了很多像这样的崩溃报告:

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

它不会影响上述方法 - 它会影响使用NSTask的任何代码。我做了一些研究,并建议修复权限可以解决问题,但这不是很有用,因为我无法与报告这些崩溃的用户联系。我已经将代码放在try catch块中 - 我还能做些什么来最小化或消除它?

我编写了以下函数来包装NSTask

代码:

+ (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;
}

1 个答案:

答案 0 :(得分:1)

如果重新启动修复了问题,那么似乎最小化文件句柄可能有助于防止此问题。但是,我仍然会尝试在本地重现问题,方法是创建大量文件句柄而不关闭它们,这样你就可以确定是什么导致了崩溃。

我看到你在创建文件句柄时将其作为参数传递。这可以防止您控制何时关闭该文件句柄。我会保留对文件句柄的引用,以便您可以在不再使用时关闭它:

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

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

...
//outputFileHandle is no longer used
[outputFileHandle close];