2

背景背景:

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


我的问题:

XPC 服务似乎将运行我的代码的线程的堆栈大小设置为,这是除主线程之外的线程512kb的 macOS 默认值。(默认情况下,主线程的堆栈大小。)8MB

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

注意:我知道这是问题所在,因为如果我在我的应用程序的主线程上运行完全相同的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

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

所以,我然后尝试使用但是,仍然从该块内返回,强制在主线程上完成工作。此外,如果我使用,我得到,这表明运行此代码的线程有一个堆栈。极好的。dispatch_async(dispatch_get_main_queue() ^{...});-isMainThreadfalse[NSThread currentThread] stackSize]524288512kb

我还尝试过在运行时使用setrlimit(). 这并没有解决问题。

我读过一堆文档。XPC 服务使用哪些线程以及它们如何使用它们的细节似乎是我们不应该担心的实现细节。

4

1 回答 1

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];
}

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

有人有更好的方法吗?

于 2017-03-02T10:07:37.153 回答