【问题标题】:Objective C Command Failing When Run Through OSX Cron通过 OSX Cron 运行时,Objective C 命令失败
【发布时间】: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


【解决方案1】:

答案是你不知道。您不再在 OSX 上为您正在编码的应用程序使用 cron。相反,切换到LaunchAgent。当然,Apple 保留它是为了支持 POSIX,因此可能会保留很长时间,但即使是他们的网站也鼓励人们不再使用 cron 进行应用程序编码。

"注意:虽然仍然支持,但不推荐使用 cron 解决方案。它已被弃用,取而代之的是 launchd。”

来源:https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html

不幸的是,LaunchAgents 还不支持(至少在 10.11.4 中)支持 cron 样式的语法。 (是的,我已经为您向 Apple 提交了该建议。)因此,没有使用破折号、逗号或反斜杠。相反,它只支持一个整数和多个块来创建每个时间帧。如果这还不够合适,那么至少设置最短的时间范围,然后在您启动的任何内容中执行其余代码,例如,如果您只想在每月的第一个星期一运行某些东西, LaunchDaemon 在前 7 天启动,但如果不是每月的第一个星期一,您的应用程序会关闭。

【讨论】:

    猜你喜欢
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    相关资源
    最近更新 更多