<div dir="ltr"><div><div><div>I just noticed an alternative solution in the example uds_server.erl. It jumps through a number of hoops to get the priv directory even if the code server is not running:<br><br><a href="https://github.com/erlang/otp/blob/maint/lib/kernel/examples/uds_dist/src/uds_server.erl#L107-L148">https://github.com/erlang/otp/blob/maint/lib/kernel/examples/uds_dist/src/uds_server.erl#L107-L148</a><br><br></div>Perhaps the crypto module could do something similar in its on_load function.<br><br></div>Regards,<br></div>Magnus<br><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 19, 2015 at 7:04 PM, Magnus Henoch <span dir="ltr"><<a href="mailto:magnus@erlang-solutions.com" target="_blank">magnus@erlang-solutions.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi all,<br>
<br>
I'm trying to use Erlang distribution over TLS ("-proto_dist inet_tls"), and I've stumbled upon an interesting race condition.<br>
<br>
The kernel supervisor starts the distribution subsystem before it starts the code server.  Therefore, it's possible for another node to establish a connection to the distribution port while the code server is not yet running.  (Apologies for not providing a recipe for reproducing this; I could work on that if that would be useful.)<br>
<br>
In that case, the TLS distribution module eventually calls ssl:ssl_accept/2 on the connection socket.  This in turn will eventually call crypto:supports/0.  That's when I got this error:<br>
<br>
{error_logger,{{2015,10,19},{15,1,22}},<br>
supervisor_report,<br>
[{supervisor,{local,ssl_dist_sup}},<br>
 {errorContext,child_terminated},<br>
 {reason,{undef,[{crypto,supports,[],[]},<br>
                 {tls_record,supported_protocol_versions,1,[{file,"tls_record.erl"},{line,322}]},<br>
                 {tls_record,supported_protocol_versions,0,                  [{file,"tls_record.erl"},{line,257}]},<br>
                 {ssl,handle_options,1,[{file,"ssl.erl"},{line,617}]},<br>
                 {ssl,ssl_accept,3,[{file,"ssl.erl"},{line,228}]},<br>
                 {ssl_tls_dist_proxy,accept_loop,4,[{file,"ssl_tls_dist_proxy.erl"},{line,152}]}]}},<br>
 {offender,[{pid,<0.22.0>},<br>
            {name,ssl_tls_dist_proxy},<br>
            {mfargs,{ssl_tls_dist_proxy,start_link,[]}},<br>
            {restart_type,permanent},<br>
            {shutdown,4000},<br>
            {child_type,worker}]}]}<br>
<br>
(though it was formatted as one long line, using the kernel's primitive error reporter.)<br>
<br>
Why is that function undefined, you ask.  That's because the crypto module has an on_load function, which calls code:priv_dir/1 to figure out where the NIF library is.  Since the code server isn't running yet, code:priv_dir/1 raises an exception, and as I just learnt from reading the documentation, if an on_load function raises an exception (or returns anything but 'ok'), the module is unloaded - and thus we get an 'undef' error.<br>
<br>
(This will make the ssl_tls_dist_proxy process terminate.  Its supervisor will restart it, but that doesn't help: it has lost its listening socket, and net_kernel won't ask it to open another one, rendering the node "alive" but unable to receive connections for distribution - but that's a separate issue.)<br>
<br>
I came up with the attached patch, which waits for the code server to start before proceeding, and that fixes the problem for me. What do you think about it?  Might there be a better way to solve this?<br>
<br>
Regards,<br>
Magnus<br>
<br>
</blockquote></div><br></div>