XPC 服务:提高工作线程上的堆栈大小

Posted

技术标签:

【中文标题】XPC 服务:提高工作线程上的堆栈大小【英文标题】:XPC Service: Raise Stack Size on Worker Thread 【发布时间】:2017-03-02 09:12:13 【问题描述】:

背景背景:

我有一个为 macOS 10.11+ 构建的应用程序。这个应用程序需要运行一些可能偶尔会崩溃的第三方代码(The Libsass compiler)。为了避免关闭我的整个应用程序,我创建了一个运行此代码的 XPC 服务(使用 NSXPCConnection 和 Xcode 中的标准 XPC 服务模板)。


我的问题:

XPC 服务似乎正在将运行我的代码的线程的堆栈大小设置为512kb,这是 macOS 对主线程其他线程的默认设置。 (主线程的栈大小默认为8MB。)

Libsass 编译器有时会在某些涉及深度递归(因此有很多堆栈帧)的文件上发生堆栈溢出而崩溃。

注意: 我知道这是问题所在,因为如果我在应用程序的主线程上运行 exact 相同的 Libsass 序列(不使用 XPC),一切正常,并且堆栈溢出永远不会发生。


我需要什么:

一种增加 XPC 服务执行工作的线程堆栈大小的方法。


我尝试过的:

我已经将-Wl,-stack_size,4000000 添加到我的 XPC 服务目标的“其他链接器标志”构建设置中。这会将堆栈大小设置为 64MB(允许的最大值)。构建后,我在 Finder 中检查 XPC 包,并使用以下命令验证链接器是否正确应用了此标志:

otool -lV codekit-libsass-service.xpc/Contents/MacOS/codekit-libsass-service | grep stack

产生这个输出:stacksize 67108864,表示堆栈大小确实设置为64MB

问题在于,这仅适用于服务的 ma​​in 线程,而我的 XPC 方法似乎没有在服务的主线程上调用。我通过使用[NSThread isMainThread] 验证了这一点,当在我的 XPC 方法中调用它时返回false

所以,我然后尝试强制使用 dispatch_async(dispatch_get_main_queue() ^...); 在主线程上完成的工作,但是,-isMainThread 仍然从 within 该块返回 false .此外,如果我使用[NSThread currentThread] stackSize],我会得到524288,这表明运行此代码的线程有一个512kb 堆栈。太棒了。

我还尝试使用setrlimit() 在运行时动态提高堆栈大小。这并没有解决问题。

我已经阅读了很多文档。 XPC 服务使用哪些线程以及它们如何使用它们的细节似乎是我们不应该担心的实现细节。

【问题讨论】:

【参考方案1】:

虽然这可行,但我无法想象这是最好的方法。基本上,如果你有这样的 XPC 方法:

- (void) doStuffWithObject:(NSDictionary *)dict withReply:(void (^)(NSString *))reply 

    // Code that needs a bigger stack. 

那么你可以这样做:

- (void) doStuffWithObject:(NSDictionary *)dict withReply:(void (^)(NSString *))reply 

    NSThread *thread = [[NSThread alloc] initWithBlock:
    ^
         // Code that needs a bigger stack
    ];

    [thread setStackSize:67108864];     // 64MB. Must be in multiples of 4096.
    [thread start];

每次调用此方法时设置线程都会产生开销,但这是(到目前为止)我能想到的增加堆栈大小的唯一方法。

谁有更好的方法?

【讨论】:

另外:上面的代码在 ARC 环境中运行,它处理复制回复块、释放线程等。您需要在手动引用计数环境中自己执行此操作。

以上是关于XPC 服务:提高工作线程上的堆栈大小的主要内容,如果未能解决你的问题,请参考以下文章

64 位 Linux 上的 Java 线程堆栈大小

XPC 连接如何以线程方式处理?

tomcat线程优化

我可以更改 XPC 服务的服务质量级别吗?

传递线程例程多个变量和堆栈大小

创建堆栈大小为默认值 50 倍的线程时有啥危险?