【发布时间】:2016-04-14 10:03:07
【问题描述】:
我编写了一个独立的 Objective C 命令应用程序。如果我通过 LaunchDaemon 运行它,那么当 ObjC 客户端应用程序通过 DistriutedObjects 通信连接时它运行得很好。如果我在命令行运行它,它运行得很好。如果我在被 Bash 脚本调用时运行它,它运行得很好。但是,在我尝试通过 root 用户的 crontab 运行它的各种方式中,它会生成有关指针分配的崩溃报告:
Apr 14 05:27:00 volomike cron[72531]: cron(72531,0x7fff7d2fa000) malloc: *** error for object 0x7fb9c8400213: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Apr 14 05:27:00 volomike diagnosticd[70689]: error evaluating process info - pid: 72531, puniqueid: 72531
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.vix.cron[72531]): Service exited due to signal: Abort trap: 6
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.apple.ReportCrash.Root[72550]): Endpoint has been activated through legacy launch(3) APIs. Please switch to XPC or bootstrap_check_in(): com.apple.ReportCrash.DirectoryService
Apr 14 05:27:00 volomike ReportCrash[72550]: Saved crash report for cron[72531] version 39 to /Library/Logs/DiagnosticReports/cron_2016-04-14-052700_volomike.crash
该崩溃报告的重要部分如下:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Application Specific Information:
abort() called
*** error for object 0x7fb9c8400213: pointer being freed was not allocated
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff9490ff06 __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff9c45e4ec pthread_kill + 90
2 libsystem_c.dylib 0x00007fff9345b6e7 abort + 129
3 libsystem_malloc.dylib 0x00007fff9c02f041 free + 425
4 cron 0x000000010367aa41 0x103677000 + 14913
5 cron 0x000000010367a7e4 0x103677000 + 14308
6 cron 0x0000000103679572 0x103677000 + 9586
7 cron 0x000000010367925a 0x103677000 + 8794
8 cron 0x000000010367885e 0x103677000 + 6238
9 libdyld.dylib 0x00007fff949835ad start + 1
以各种方式,我用这些不同的 cron 行完成了它,但是当尝试调用命令时它们会立即崩溃,即使我让 NSLog() 将内容写入 /var/log/system.log all从 main 开始到应用程序结束的过程中,什么都没有写——就像当 cron 尝试调用我的命令时,它会立即死亡,并报告有关指针分配的崩溃报告。
41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched
41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched &
41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched
41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched &
再次注意,如果我使用'/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched,它运行得很好,/bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched 也一样,'/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched 也一样
我什至做了一个变体,其中 cron 调用我的 mytoolcommand.sh 脚本并简单地将 Hello World 写入 /tmp/out.txt,它运行得很好。所以,我知道我的 crontab 正在工作。
你能帮我弄清楚我做错了什么吗?一些疑似问题:
也许 OSX El Capitan 出于某种原因关闭了我的应用程序,例如未正确签名。 (我现在正在调试。我之前从未出现过签名问题,除非它处理 .app 文件夹。此外,我可以从命令行正常运行它而不会出现签名警告。)
我立即从 main() 加载了调试消息。他们应该写入/var/log/system.log,但他们不是。这告诉我应用程序在被 cron 调用时立即崩溃。那么,我需要将一些特殊的东西加载到我的应用程序的库中,以便它在 cron 下调用时能够正常运行吗?
发展
我怀疑 El Capitan Gatekeeper 可能是原因。所以,我在 main.mm 文件中创建了一个简单的 Objective C 控制台应用程序并编译。
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *sTest = @"Hello World";
[sTest writeToFile:@"/tmp/test.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
return 0;
}
Cron 似乎运行得很好,所以它看起来不像是 Gatekeeper 问题。
我解决了这个问题,但只是短暂的。我在一个全新的项目中重新编译了项目,复制了源代码和设置。然后我通过 cron 运行命令大约 4 次没有问题。但是,当我第五次运行它时,它再次失败并继续失败。
所以,我想我将不得不弄清楚如何将其转换为 LaunchAgent。
【问题讨论】:
-
那是
cron崩溃(我假设是forked 副本),而不是您的程序。这听起来很难解决。我还以为cron在 OSX 下被弃用了?还有/q和/sched参数是怎么回事? -
好的,所以它是 cron。也许 cron 无法处理加载 Objective C 应用程序,只能处理内存要求低的 C 或 C++ 应用程序。 /q 和 /sched 是传递给我的 Obj C 应用程序的参数,用于“快速、预定的扫描”——它是我正在使用第三方 API 开发的恶意软件扫描程序。 Cron 并没有完全被弃用—— man 文件还没有提到这一点。 OSX 也希望与 POSIX 兼容,而 cron 就是其中的一部分。我仍然比 LaunchDaemon 计划更习惯 cron。相关:apple.stackexchange.com/a/96883/6907
-
我没有太多建议。我怀疑
cron关心程序是用什么语言编写的,但是如果程序不使用 Cocoa(即 UI 应用程序),那么我认为几乎不需要使用 Objective-C,如果您使用的是 Foundation,那么您需要管理运行循环(= 麻烦)。此外,/仅在 Windows 程序中用于传递参数;在类 UNIX 系统下,它是-。如果我被期望使用/在 Mac 程序上传递参数,作为用户,我会感到非常震惊。 -
/ 与 - 的优点。我需要切换它。
-
学习
getopt()(或GNU扩展版)。
标签: objective-c macos pointers cron crash