Моя программа, похоже, страдает от очень трудно воспроизводимой ошибки: однажды в голубой луне, когда пользователь кладет свой Mac в спящий режим, а затем снова запускает его, один из дочерних процессов моей программы завершится аварийно после того, как Mac просыпается.
Когда это происходит, механизм аварийного репортера Apple надежно сообщает трассировку стека, как этот:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x967f9a6a __pthread_kill + 10
1 libsystem_c.dylib 0x9003dacf pthread_kill + 101
2 libsystem_c.dylib 0x900744f8 abort + 168
3 com.meyersound.VirtualD-Mitri 0x0014438e muscle::CrashSignalHandler(int) + 190
4 libsystem_c.dylib 0x9002886b _sigtramp + 43
5 ??? 0xffffffff 0 + 4294967295
6 com.meyersound.VirtualD-Mitri 0x001442d0 muscle::ParsePortArg(muscle::Message const&, muscle::String const&, unsigned short&, unsigned long) + 80
7 com.meyersound.VirtualD-Mitri 0x005b3393 qnet::RepDBPeer::Pulse(muscle::PulseNode::PulseArgs const&) + 1187
8 com.meyersound.VirtualD-Mitri 0x0015717b muscle::PulseNode::PulseAux(unsigned long long) + 203
9 com.meyersound.VirtualD-Mitri 0x000cfb90 muscle::ReflectServer::ServerProcessLoop() + 3232
10 com.meyersound.VirtualD-Mitri 0x00607c7e dcasldmain(int, char**) + 2222
11 com.meyersound.VirtualD-Mitri 0x0072c14d dmitridmain(int, char**) + 4749
12 com.meyersound.VirtualD-Mitri 0x0000bc3a main + 4938
13 com.meyersound.VirtualD-Mitri 0x000061ab _start + 209
14 com.meyersound.VirtualD-Mitri 0x000060d9 start + 41
Это все хорошо, кроме (кий жуткая музыка) — это логически невозможно. В частности, не только мой RepDBPeer::Pulse()
метод никогда не вызывать ParsePortArg
процесс сбоя никогда не вызывает ParsePortArg
в любом месте! (Я собрал весь свой исходный код дважды, чтобы убедиться)
Итак, мой вопрос, что же мне пытается сказать эта трассировка стека? Является ли это наиболее вероятным случаем стека потока 0, настолько сильно поврежденного, что механизм отслеживания стека сошел с рельсов и выдал невинного наблюдателя за преступника? Или, возможно, механизм пробуждения Apple каким-то образом «запрыгнул» счетчиком программы в ParsePortArg () (после чего возникшая путаница вызвала сбой)? Или здесь происходит какая-то более глубокая магия, которую я даже не могу себе представить?
Рассматриваемый процесс сбоя — это ванильный не-GUI фоновый процесс, который является дочерним процессом, порожденным процессом Qt GUI, для чего это стоит.
Я предполагаю, что у вас включена некоторая оптимизация. Там нет магии, чтобы сложить следы. Они становятся все более размытыми (читаются как «менее точные») после того, как код вставлен или опущен, что и делает оптимизатор C ++.
В случае ParsePortArg
, в конце этой строки стоит +80, что означает 80 байтов перед точкой входа этой функции в сегменте кода. Это указывает на истинный адрес указателя инструкции в 0x001442d0
, а также ParsePortArg
является ближайшим символом, на который угадан дамп стека. Вы были правы, предполагая, что это была красная сельдь.
За исключением любых других данных, я бы сделал очень осторожное предположение, что ваша программа ожидает, что какой-то указатель останется действительным, что недопустимо при пробуждении из спящего режима. Посмотрите на разборку для инструкции по этому адресу. Бьюсь об заклад, адрес памяти пытается быть прочитанным.
Других решений пока нет …