svc #128 в pthread_kill неожиданно взламывает отладчик?

Я вижу неожиданные перерывы в работе отладчика в Xcode, связанные с инструкцией svc #128 ARM из вызова pthread_kill для подачи сигнала другому потоку. Я видел это для ряда вопросов StackOverflow, связанных с этой проблемой на iOS, но они мне не помогли. В этом случае повторное выполнение Debug->Continue (^⌘Y) решает проблему, и выполнение продолжается без каких-либо явных побочных эффектов. Кроме того, если оно запущено вне отладчика, приложение работает нормально. Моя цель — понять, почему это происходит, и избежать взлома отладчика, за исключением случаев, когда это необходимо.

Есть ли параметр Xcode, который я мог случайно установить, который прерывает эти сигналы?

Я использую транспилятор Google Java to Objective-C (j2objc), хотя другие разработчики iOS упоминали об этой проблеме, не связанной с j2objc, поэтому я не верю, что это причина. Это происходит, когда проект j2objc Java Runtime Environment Emulation сигнализирует другим заблокированным потокам. Он постоянно имеет 3 потока для подачи сигнала. После трехкратного выполнения Debug->Continue выполнение программы продолжается без проблем или явных побочных эффектов. В проекте нет точек останова.

Приложение порождает другой поток при запуске, который использует класс 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, в него встроен код цели-C, который сохраняется транспилером j2objc:

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 - предотвращает проблему, но, очевидно, не решение оставить сокет открытым


person brunobowden    schedule 04.01.2015    source источник


Ответы (1)


Есть хитрость в том, чтобы попросить Xcode игнорировать сигналы. Мне любопытно, почему Xcode по умолчанию настроен на прерывание сигналов, но вот и все. Обратите внимание, что метод зависит от используемого вами языка — я отредактировал его, чтобы расширить пример до Swift:

Постоянная настройка LLDB (в Xcode 4.3.2), чтобы не останавливаться на сигналах

person brunobowden    schedule 04.01.2015