<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=SV link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'>Prior to OTP 22.0 resource destructors were called directly by the thread that happened to decrease the reference counter down to zero.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'>From OTP 22.0 resource destructors are scheduled. This in order to ensure a stable known execution context for the destructor callback. So it may not have executed when erlang:garbage_collect  returns, but will very soon (unless you have a very overloaded system or a bug preventing ref counter from reaching zero).<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'><o:p> </o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'>To not get dependent on the garbage collector to release large memory blocks (or other limited OS resources) you can solve it (like a lot of other problems) with an extra level of indirection. Keep the resource object small and allocate the large block separately. Then you can deallocated the big block whenever you want and mark the resource as dead with a NULL pointer for example.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'><o:p> </o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'>/Sverker, Erlang/OTP<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'><o:p> </o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'><o:p> </o:p></span></p><p class=MsoNormal><b><span lang=EN-US>From:</span></b><span lang=EN-US> erlang-questions <erlang-questions-bounces@erlang.org> <b>On Behalf Of </b>José Valim<br><b>Sent:</b> den 23 november 2020 20:24<br><b>To:</b> Erlang <erlang-questions@erlang.org><br><b>Subject:</b> Are NIF resources meant to be destroyed immediately on GC?<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p><div><div><p class=MsoNormal>Hi everyone,<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>We are working on some code that allocates large chunks of memory inside a NIF and ties them to a resource (using enif_alloc_resource + enif_make_resource). While running some tests, I noticed that we were holding onto these resources for longer than we wanted to, so we have added calls to erlang:garbage_collect/1. In a nutshell, the code looks like this:<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div style='margin-left:30.0pt'><p class=MsoNormal>my_nif:function_allocates_large_memory(),<o:p></o:p></p></div><div style='margin-left:30.0pt'><p class=MsoNormal>erlang:garbage_collect(),<o:p></o:p></p></div><div style='margin-left:30.0pt'><p class=MsoNormal>my_nif:check_if_resource_has_been_destroyed().<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>In our runs, it seems that the resource has not yet been destroyed in most cases. However, if we do add a sleep after garbage collection, then the odds of it being destroyed increases as we increase the sleep interval.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Is this correct? Even if the resource was garbage collected, the destructor may not have been called? Or is this actually a big in our software that we should look deeper into?<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Thank you,<o:p></o:p></p></div></div></div></body></html>