Reputation: 595
I am trying to understand the exact semantics of erlang:trace_delivered/1
in order to determine whether this function can be suitably used to solve a problem I am currently facing. The problem is as follows.
Suppose there is a tracee process X
, a tracer Y
tracing X
, and a third process, Z
. Tracer Y
is initially tracing X
. Process Z
is tasked with the responsibility of stopping Y
from tracing X
by calling erlang:trace(X, false)
. This call is arbitrarily effected by Z
whilst X
is running. Thereafter, Z
is also to issue a special message stopped
to tracer Y
which signals to Y
that Z
has indeed stopped Y
from tracing X
.
I would like to guarantee that the special stopped
message is delivered to Y
's mailbox after all other trace messages have been delivered to Y
. To my knowledge, Erlang does not guarantee the ordering of messages sent by different processes to a single process. Concretely in my case this means that tracer Y
can, for instance, receive the stopped
issued by Z
before the trace event messages due to tracee X
. I read about erlang:trace_delivered/1
, and was planning to address my problem using the following code inside the implementation of Z
:
...
erlang:trace(X, false),
Ref = erlang:trace_delivered(X),
receive
{trace_delivered, X, Ref} ->
Y ! stopped
end.
...
A somewhat similar example is provided in the docs (quoted below):
Example: Process
A
is Tracee, portB
is tracer, and processC
is the port owner ofB
.C
wants to closeB
whenA
exits. To ensure that the trace is not truncated,C
can callerlang:trace_delivered(A)
whenA
exits, and wait for message{trace_delivered, A, Ref}
before closingB
.
My example differs from the one in the docs in these two respects:
C
knows the exact point of execution of A
prior to invoking erlang:trace_delivered(A)
; in my case, I do not know the point X
is in when erlang:trace_delivered(X)
is invoked by Z
.C
, my process Z
switches off tracing on X
before invoking erlang:trace_delivered(X)
.What are the semantics of erlang:trace_delivered/1
in this case?
{trace_delivered, X, Ref}
is received by process Z
after all trace messages have been delivered to tracer Y
? erlang:trace_delivered/1
automatically keep track of the point at which the execution of tracee X
is at to be able to provide the aforementioned guarantee?Your help is greatly appreciated!
Upvotes: 1
Views: 136
Reputation: 4916
You are correct about the ordering of messages. If process A
sends multiple messages to process B
they will be guaranteed to arrive in order. If A
sends multiple messages to processes B
and C
the message order will only be guaranteed per-process. So for example:
A
sends B
message 1 A
sends C
message 2 A
sends B
message 3 A
sends C
message 4The only guarantees in this scenario is that B
will receive message 1 before message 3, and C
will receive message 2 before message 4.
To answer your questions:
No, if erlang:trace_delivered/1
is invoked prior to other trace events being generated those messages will arrive later. The docs only guarantee that prior trace messages are delivered prior to {trace_delivered, ...}
:
When it is guaranteed that all trace messages are delivered to the tracer up to the point that Tracee reached at the time of the call to erlang:trace_delivered(Tracee), then a {trace_delivered, Tracee, Ref} message is sent to the caller of erlang:trace_delivered(Tracee) .
The guarantees around erlang:trace_delivered/1
always hold true. But it doesn't guarantee that {trace_delivered, ...}
will always be the last message.
Upvotes: 1