0

我在 Xcode 中看到调试器出现意外中断,这与svc #128调用 pthread_kill 以向另一个线程发出信号的 ARM 指令有关。我已经在 iOS 上看到了一些与此问题相关的 StackOverflow 问题 - 但它们对我没有帮助。在这种情况下,重复执行 Debug->Continue (^⌘Y) 可以解决问题并继续执行而没有任何明显的副作用。此外,如果它在调试器之外运行,则该应用程序可以正常工作。我的目标是了解为什么会发生这种情况,并避免闯入调试器,除非是有意的。

是否有我可能不小心设置的 Xcode 设置中断了这些信号?

我正在使用 Google 的 Java to Objective-C Transpiler (j2objc),尽管其他 iOS 开发人员提到了这个与 j2objc 无关的问题,所以我不认为这是原因。当 j2objc Java Runtime Environment Emulation 项目向其他阻塞线程发出信号时,就会发生这种情况。它始终有 3 个线程要发出信号。执行 Debug->Continue 3 次后,程序继续执行,没有问题或明显的副作用。项目中没有断点。

应用程序在启动时生成另一个使用 Java DatagramSocket 类的线程。Java 代码工作正常。转译的 Objective-C 代码也可以正常工作,除了烦人的调试器中断。

这是中断时的堆栈帧:

main (1)Queue : com.apple.main-thread (serial)
#0  0x0000000195557270 in __pthread_kill ()
#1  0x00000001955f5228 in pthread_kill ()
// Java Runtime Environment Emulation
#2  0x00000001002f7898 in +[AsynchronousSocketCloseMonitor signalBlockedThreads:] ()
#3  0x00000001002f9754 in LibcoreIoIoBridge_closeSocketWithJavaIoFileDescriptor_ ()
#4  0x00000001001f4894 in -[JavaNetPlainDatagramSocketImpl close] ()
// My Code
#5  0x000000010016db88 in <my code>...

内核 pthread_kill 方法中的本地程序集...

libsystem_kernel.dylib`__pthread_kill:
0x195557268:  movz   x16, #328
0x19555726c:  svc    #128
// The debugger lands on the following line but I think svc #128 is the cause
0x195557270:  b.cc   0x195557288               ; __pthread_kill + 32
0x195557274:  stp    fp, lr, [sp, #-16]!
0x195557278:  mov    fp, sp
0x19555727c:  bl     0x19553e59c               ; cerror_nocancel
0x195557280:  mov    sp, fp
0x195557284:  ldp    fp, lr, [sp], #16
0x195557288:  ret

堆栈帧中最接近的非内核函数是signalBlockedThreads. 当我的代码关闭套接字时,signalBlockedThreads遍历所有线程,寻找那些针对特定文件描述符阻塞的线程(我假设这对应于刚刚关闭的端口号)。对于那些相关的阻塞线程,它们每个都用 pthread_kill 发出信号。方法代码复制如下。

对于文件链接,即使这是一个 Java 文件,它也嵌入了由 j2objc 转译器保留的 Objective-C 代码:

https://github.com/google/j2objc/blob/765354b620b2c0248945b27062209620d4cf5e40/jre_emul/android/libcore/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java#L89

+ (void)signalBlockedThreads:(int)fd {
  pthread_mutex_lock(&blockedThreadListMutex);
  for (AsynchronousSocketCloseMonitor* it = blockedThreadList; it != NULL; it = it->mNext) {
    if (it->mFd == fd) {
      // MY ADDED COMMENT: BLOCKED_THREAD_SIGNAL == SIGUSR2 in this code
      pthread_kill(it->mThread, BLOCKED_THREAD_SIGNAL);
      // Keep going, because there may be more than one thread...
    }
  }
  pthread_mutex_unlock(&blockedThreadListMutex);
}

调试尝试没有成功: * 添加和删除“所有异常”断点 - 这没有透露任何内容 * 删除 closeSocket 调用 - 避免问题但显然不是保持套接字打开的解决方案

4

1 回答 1

1

要求 Xcode 忽略信号有一个技巧。我很好奇为什么 Xcode 默认配置为中断信号,但你去吧。请注意,该方法根据您使用的语言而有所不同 - 我已经对其进行了编辑以将示例扩展到 Swift:

永久配置 LLDB(在 Xcode 4.3.2 中)不停止信号

于 2015-01-04T18:55:38.423 回答