<p dir="auto">The following code snippet emits a very odd error message (requires the GSL library):</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="type gsl_error_handler_t end

custom_gsl_error_handler = convert(Ptr{gsl_error_handler_t}, cfunction(error, Void, ()))

function set_error_handler(new_handler::Ptr{gsl_error_handler_t})
    output_ptr = ccall( (:gsl_set_error_handler, :libgsl),
        Ref{gsl_error_handler_t}, #&lt;--- User error: should be Ptr{...}
        (Ptr{gsl_error_handler_t}, ), new_handler )
end

set_error_handler(custom_gsl_error_handler)"><pre class="notranslate">type gsl_error_handler_t <span class="pl-k">end</span>

custom_gsl_error_handler <span class="pl-k">=</span> <span class="pl-c1">convert</span>(Ptr{gsl_error_handler_t}, <span class="pl-c1">cfunction</span>(error, Void, ()))

<span class="pl-k">function</span> <span class="pl-en">set_error_handler</span>(new_handler<span class="pl-k">::</span><span class="pl-c1">Ptr{gsl_error_handler_t}</span>)
    output_ptr <span class="pl-k">=</span> <span class="pl-c1">ccall</span>( (<span class="pl-c1">:gsl_set_error_handler</span>, <span class="pl-c1">:libgsl</span>),
        Ref{gsl_error_handler_t}, <span class="pl-c"><span class="pl-c">#</span>&lt;--- User error: should be Ptr{...}</span>
        (Ptr{gsl_error_handler_t}, ), new_handler )
<span class="pl-k">end</span>

<span class="pl-c1">set_error_handler</span>(custom_gsl_error_handler)</pre></div>
<p dir="auto">Result:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ERROR: UndefVarError: result not defined
 in include_from_node1 at ./loading.jl:316
 in process_options at ./client.jl:275
 in _start at ./client.jl:375"><pre class="notranslate"><code class="notranslate">ERROR: UndefVarError: result not defined
 in include_from_node1 at ./loading.jl:316
 in process_options at ./client.jl:275
 in _start at ./client.jl:375
</code></pre></div>
<p dir="auto"><code class="notranslate">result</code> is not defined in this code, nor is it ever used at the user level, so this error is rather cryptic.</p>
<p dir="auto">Observed on release-0.4 and master.</p>
<h3 dir="auto">TL;DR</h3>
<p dir="auto">This is a runtime debug option proposed by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/carnaval/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/carnaval">@carnaval</a> to catch common misuse of <code class="notranslate">ccall</code> which could otherwise cause corruption that's hard to debug.</p>
<h3 dir="auto">The problem</h3>
<blockquote>
<p dir="auto">...... when someone trashed a tag. Often happens in pools with OOB stores, ...... Unfortunately it's<br>
the only "downside" of having an almost too easy C FFI.<br>
        -- Oscar Blumberg (<a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/carnaval/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/carnaval">@carnaval</a>) at <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="91967127" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/11945" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/11945/hovercard?comment_id=117165822&amp;comment_type=issue_comment" href="https://github.com/JuliaLang/julia/issues/11945#issuecomment-117165822">#11945 (comment)</a> <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="91967127" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/11945" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/11945/hovercard?comment_id=117172936&amp;comment_type=issue_comment" href="https://github.com/JuliaLang/julia/issues/11945#issuecomment-117172936">#11945 (comment)</a></p>
</blockquote>
<p dir="auto">The issue here is that it is very/too easy to pass a pointer to an object to a C function with <code class="notranslate">ccall</code>. This is one of the awesomeness of Julia. However, if the user makes a mistake about the C api, commonly not allocating enough memory, the c function might write to memory that is not meant to be written which could corrupt the GC managed memory and crashes with spectacular backtrace (pages of <code class="notranslate">push_root</code>).</p>
<p dir="auto">This happens surprisingly often. It can be caused by making mistake on the c-interface or <code class="notranslate">ccall</code> (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="91967127" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/11945" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/11945/hovercard" href="https://github.com/JuliaLang/julia/issues/11945">#11945</a>), upstream abi breakage (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="89377105" data-permission-text="Title is private" data-url="https://github.com/JuliaInterop/ZMQ.jl/issues/83" data-hovercard-type="issue" data-hovercard-url="/JuliaInterop/ZMQ.jl/issues/83/hovercard" href="https://github.com/JuliaInterop/ZMQ.jl/issues/83">JuliaInterop/ZMQ.jl#83</a>) or just not careful enough on refactoring (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="95061324" data-permission-text="Title is private" data-url="https://github.com/JuliaGPU/OpenCL.jl/issues/65" data-hovercard-type="pull_request" data-hovercard-url="/JuliaGPU/OpenCL.jl/pull/65/hovercard" href="https://github.com/JuliaGPU/OpenCL.jl/pull/65">JuliaGPU/OpenCL.jl#65</a>) (I'm only aware of these but there's probably more...).</p>
<p dir="auto">This kind of issue is also relatively hard to debug as they happens randomly and usually crashes in totally unrelated places. With <a href="https://github.com/JuliaLang/julia/issues/11313#issuecomment-102833790" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/11313/hovercard">@carnaval 's guide</a> on GC debugging, it is not impossibly to figure out the issue but is nontheless much harder than using <code class="notranslate">ccall</code> (unless, of course, if <a href="https://github.com/keno/">someone</a> can <a href="https://github.com/Keno/Cxx.jl">somehow</a> integrate lldb (or sth else) in julia).</p>
<h3 dir="auto">Solution</h3>
<p dir="auto">It's very hard (if not impossible) to detect this issue ahead of time but it would really help debugging and fixing the issue if the error is raised as early as possible (at the <code class="notranslate">ccall</code> site). One way to do that, proposed by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/carnaval/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/carnaval">@carnaval</a> , is to allocate some extra memory with known random content for each object and check after each ccall to make sure the c function didn't modify them.</p>
<h3 dir="auto">Implementation</h3>
<p dir="auto">AFAICT, one (only?) missing part for implementing this is to figure out on which objects/memory regions this check should be performed. There are several possibilities that I can think of:</p>
<ol dir="auto">
<li>
<p dir="auto">Do it statically in codegen.</p>
<p dir="auto">This is hard because <code class="notranslate">ccall</code> only see the pointer after <code class="notranslate">unsafe_convert</code> (or the user may even convert using <code class="notranslate">pointer</code> directly).</p>
</li>
<li>
<p dir="auto">Scan every objects.</p>
<p dir="auto">This should be doable and should be relatively easy to implement (just add an extra call into the GC after each <code class="notranslate">ccall</code> site). The obvious problem would be performance. This can probably be implemented as a more aggressive mode to catch corner cases but should probably not be the default one.</p>
</li>
<li>
<p dir="auto">Let the GC figure out if the pointer should be sanitized.</p>
<p dir="auto">I think this is the best compromise between performance and implementation difficulty. The idea is to use the machinery for conservative stack scan to figure out if a pointer is pointing to a GC object. The codegen will just pass all pointer arguments to the GC and do all the work there. An additional benefit of this is that it can be used to verify that the object is properly rooted.</p>
</li>
</ol>
<h3 dir="auto">Other concern</h3>
<ul dir="auto">
<li>
<p dir="auto">Stack allocated memory</p>
<p dir="auto">Currently only limited to the <code class="notranslate">&amp;</code> <code class="notranslate">ccall</code> operator and can be special cased. If we have more general stack allocation of mutable object, we can probably keep track of them in this mode the same way we keep the gc frame.</p>
</li>
<li>
<p dir="auto">Concurrency</p>
<p dir="auto">In order to support multiple thread using the same object, the random data in the padding should probably be assigned at allocation time and never changes afterword (i.e. cannot be filled just before <code class="notranslate">ccall</code>).</p>
</li>
<li>
<p dir="auto">Mixing generated code with and without option (e.g. running in this mode with sysimg generated without such option)</p>
<p dir="auto">The GC should keep track of whether each object has padding allocated (heap allocated ones should be consistent, stack allocation might need more detail tracking) and do the check accordingly.</p>
</li>
</ul>