Strace исправляет зависший процесс

У меня есть однопоточный процесс Unix, который общается по протоколу TCP с другими процессами.

Проблема в следующем. Когда я запускаю процесс, он зависает (без занятого цикла), пока я не убью его.

Самое смешное, что, как только я присоединяюсь к нему с помощью strace, он продолжает работать с ожидаемым поведением, как будто не было никаких проблем вообще. (всегда воспроизводимый)

Что может быть причиной такого поведения? Какое влияние оказывает влияние на состояние процесса?

Обновление: причина, по которой strace изменил поведение, была в том, что мы использовали openonload с ошибкой. Как только мы подключили strace, стек был перенесен обратно в ядро, и проблема исчезла.

3 ответа

Много лет спустя, так что, вероятно, с совершенно другой основной причиной, этот пост в блоге объясняет, почему подключение трассировщика может исправить зависшие системные вызовы: https://ayende.com/blog/198849-C/production-postmortem-the-heisenbug-server?Key=1eeda567-02a8-4bbb-b90f-557523973233.

Цитирование справочной страницы ptrace :

Некоторые системные вызовы возвращают значение EINTR, если сигнал был отправлен

tracee, но доставка была подавлена ​​трассировщиком. (Это очень типичная операция: обычно ее делают отладчики при каждом подключении, чтобы не вводить фиктивный SIGSTOP). Начиная с Linux3.2.9, затронуты следующие системные вызовы (этот список, вероятно, неполный): epoll_wait(2) и read(2) из ​​файлового дескриптора inotify(7). Обычный симптом этой ошибки заключается в том, что когда вы присоединяетесь к неактивному процессу с помощью команды

          strace -p <process-ID>

то вместо обычного и ожидаемого однострочного вывода, такого как

          restart_syscall(<... resuming interrupted call ...>_

или

          select(6, [5], NULL, [5], NULL_

("_" обозначает позицию курсора), вы наблюдаете более одной строки. Например:

           clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0
    epoll_wait(4,_

Что здесь не видно, так это то, что процесс был заблокирован в epoll_wait(2) до того, как к нему подключилась strace(1). Присоединение вызвало возврат epoll_wait(2) в пространство пользователя с ошибкой EINTR. В этом конкретном случае программа реагировала на EINTR, проверяя текущее время, а затем снова выполняя epoll_wait(2). (Программы, которые не ожидают таких «случайных» ошибок EINTR, могут вести себя непреднамеренно при подключении strace(1).)

Скорее всего, этот вывод просто замедляет процесс, делая гораздо менее вероятными взаимные блокировки. Я видел это раньше, когда strace ИЛИ может происходить при добавлении других отладочных вызовов печати или отладки.

Тупики чаще всего встречаются при многопоточном взаимодействии. Но в вашем случае у вас есть несколько процессов. Если strace освобождает процессы каждый раз, то я предполагаю, что именно то, что вы открываете сокеты или рукопожатие на сокете, является тем, что висит. Я думаю, что буферизация и блокировка сокета могут привести вас в состояние блокировки.

Аналогичный вопрос, но с многопоточным процессом, взаимоблокировкой между потоками, а не между отдельными процессами: использование strace исправляет проблему с зависшей памятью

Трудно обобщить примеры, особенно если вы не знаете, что делают ваши разные процессы или они каким-то образом делятся ресурсами? Я попробую.,,

  1. Пример с одним объектом / ресурсом, который должен быть защищен:
    Один процесс начинает вносить изменения в объект (например, добавлять элементы в таблицу list/ db)
    Другой процесс начинает перебирать список / таблицу.
    Опасность того, что один из этих процессов повторяется в цикле, никогда не выходя из ИЛИ не делая что-то хуже, например, запись в недействительную память.

  2. Пример, в котором объект / ресурс защищен мьютексами
    Классический простой тупик с проблемой двух ресурсов. ~ проще столовых философов
    Один поток / процесс захватывает мьютекс объекта A, выполняет некоторую работу.
    Другой поток / процесс захватывает мьютекс объекта B, выполняет некоторую работу.
    Тот же поток / процесс должен обновить объект A, ожидает мьютекс для A.
    Исходный поток / процесс должен получить доступ к объекту B, ожидает мьютекс на B.
    ,,,,,,,,,,,, @ .,,,,,,,,,,
    Тишина, за исключением шума ветра и дутья, дующего по ландшафту.
    В тупике.

Если бы эта проблема была только однажды, и она была связана с обработкой сигналов, это один из источников состояния гонки в однопоточном коде.

Другие вопросы по тегам