Что сделать из «невозможного» трассировка стека после сбоя?

Моя программа, похоже, страдает от очень трудно воспроизводимой ошибки: однажды в голубой луне, когда пользователь кладет свой 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, для чего это стоит.

4

Решение

Я предполагаю, что у вас включена некоторая оптимизация. Там нет магии, чтобы сложить следы. Они становятся все более размытыми (читаются как «менее точные») после того, как код вставлен или опущен, что и делает оптимизатор C ++.
В случае ParsePortArg, в конце этой строки стоит +80, что означает 80 байтов перед точкой входа этой функции в сегменте кода. Это указывает на истинный адрес указателя инструкции в 0x001442d0, а также ParsePortArg является ближайшим символом, на который угадан дамп стека. Вы были правы, предполагая, что это была красная сельдь.

За исключением любых других данных, я бы сделал очень осторожное предположение, что ваша программа ожидает, что какой-то указатель останется действительным, что недопустимо при пробуждении из спящего режима. Посмотрите на разборку для инструкции по этому адресу. Бьюсь об заклад, адрес памяти пытается быть прочитанным.

1

Другие решения

Других решений пока нет …