Aggressive GC? Was Re: Untimely garbage collection
Scott Lystig Fritchie
fritchie@REDACTED
Sat Jul 13 22:00:46 CEST 2002
While hacking drivers, I've come across a GC question, similar to
Shawn's, that I cannot answer.
Consider this code snippet:
iolist2binary(B) when binary(B) ->
{B, size(B)};
iolist2binary(L) when List(L) ->
B = list_to_binary(L),
{B, size(B)}.
foofoo(Port, IOList) when port(Port) ->
{IOListBinary, IOListBinaryLen} = iolist2binary(IOList),
C = [ <<?S1_FOOFOO, IOListBinaryLen:32/integer>>, IOListBinary],
erlang:port_command(Port, C),
%% Vulnerability window begins here?
get_port_reply(Port).
get_port_reply(Port) ->
receive
{Port, ok} -> ok;
[...]
Assume:
1. The driver caches the pointer to IOListBinary's data
buffer. This permits the driver to avoid making a copy of
that data buffer: it can access the binary's data buffer
directly.
2. The driver is implemented asynchonously, using a separate
Pthread. Thus the VM can do other work while the driver's
Pthread takes an arbitrary amount of time to do whatever it
does.
My question: Is it possible for the VM's GC to decrement
IOListBinary's refcount in the time between execution of the
port_command() and the receive? If the VM's GC were extremely
aggressive(*), then if a GC happened at "Vulnerability window begins
here?", then:
a. IOListBinary's refcount could go to zero: if the original
IOList were a deep byte list, then foofoo() is the only thing
that knows about IOListBinary, so its refcount would drop to
zero.
b. Disaster! The driver's cached pointer to IOListBinary's
data buffer is invalid. The driver is executing independently
of the VM's Pthread, so there's no guarantee that the driver
will use the pointer before the pointer becomes invalid.
-Scott
(*) If the GC system can figure out that a binding has not yet gone
out of scope yet *but* that binding will never be used again, then
... I'm in trouble.
More information about the erlang-questions
mailing list