Я отслеживаю процесс Эрланга, скажем, P
, вызывая BIF erlang:trace(Pid_P, true, [set_on_spawn, procs, send, 'receive'])
из какого-то процесса.Согласно документам Erlang, последний процесс становится трассировщиком для P
, который я назову Trc_Q
.
Предположим, что этот процесс P
порождает новый процесс Q
.Поскольку флаг set_on_spawn
был указан при вызове erlang:trace/3
выше, Q
будет автоматически отслеживаться также Trc_P
.
Я хочу создать new tracer, Trc_Q
и передать ему владение трассировкой Q
, чтобы полученная конфигурация соответствовала процессу P
, отслеживаемому трассировщиком Trc_P
, Q
на Trc_Q
.
Однако Erlang допускает максимум один трассировщик на процесс, поэтому я не могу достичь указанной конфигурации, вызывая erlang:trace(Pid_Q, true, ..)
из Trc_Q
.Единственный возможный способ - сделать это в два шага:
- Tracer
Trc_Q
вызывает erlang:trace(Pid_Q, false, ..)
, чтобы остановить Trc_P
от отслеживания Q
; Trc_Q
вызововerlang:trace(Pid_Q, true, ..)
снова, чтобы начать трассировку Q
.
В промежуток времени между шагами 1. и 2. выше, возможно, чтотрассировка событий по процессу Q
потеряна , потому что в этот момент нет прикрепленного трассировщика.Один из способов смягчить это - выполнить следующее:
- Приостановить процесс
Q
, вызвав erlang:suspend_process(Pid_Q)
с Trc_Q
(обратите внимание, что согласно документам Erlang, Trc_Q
остается заблокированным до Q
в конечном итоге приостанавливается виртуальной машиной); Trc_Q
вызывает erlang:trace(Pid_Q, false, ..)
, чтобы остановить Trc_P
от трассировки Q
; Trc_Q
снова вызывает erlang:trace(Pid_Q, true, ..)
, чтобы начать трассировкуQ
; - Наконец,
Trc_Q
вызывает erlang:resume_process(Pid_Q)
, чтобы Q
мог продолжить выполнение.
Из того, что я смог выяснить, пока Q
Приостановлено, сообщения, отправленные на него, ставятся в очередь, и при возобновлении Trc_Q
получает события трассировки {trace, Pid_Q, receive, Msg}
соответственно без каких-либо потерь.
У меня есть одно ограничение, которое заставило меня взглянуть на процесс приостановки / возобновления: я не могу изменить код P
или Q
, поэтому вставка выражений receive
для блокировки указанных процессов исключена.
Однако я не решаюсь использовать приостановку / возобновление, поскольку в документах Erlang прямо сказано, что они должны использоваться только для целей отладки .Есть идеи, почему это так?