Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:8:4] [ds:8:4:10] [async-threads:1] [hipe]
Elixir 1.8.0-dev (c483c9c) (compiled with Erlang/OTP 21)
~/elixir> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.5 LTS
Release: 16.04
Codename: xenial
Running mix local.hex hangs with no output. I've tracked down the hang to this line by binary-searching using of IO.puts and commenting out lines.
Commenting out the line :httpc.set_option(:ipfamily, :inet6fb4, :mix) makes the request succeed. I'm unable to find documentation on the :inet6fb4 option for set_option - actually I'm unable to find documentation for http:set_option at all. I see that there exists a function called httpc:set_options (note plural options vs option).
Mix should not hang. Commenting out the above line fixes the hang.
Root-cause is that ipv6 is misconfigured on the machine.
Adding the following to sysctl fixed it:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Possible solutions: Add a timeouts around calls to :httpc (or read_httpc) to indicate a misconfiguration to the user, and/or auto retry without ipv6/ipv4 fallback.
Great find @dymk!
Unfortunately :httpc does not have a timeout for the set_options operation. But I think we can do this:
task = Task.async(fn -> :httpc.set_option(:ipfamily, :inet6fb4, :mix) end)
_ = Task.yield(task, 5000) || Task.shutdown(task, :brutal_kill)
Can you please give it a try? Let us know if you have any questions. Thank you!
:httpc.request now appears to be the point at which the hang happens. If I had to guess, under the hood, the .set_option call is blocking in the :mix process, so .request is also hanging.
@dymk maybe we should wrap everything in a task then? but then we should give it a higher timeout. maybe of 30s or even more. at this point i don't know if it will be useful :(
Or maybe we could keep the code as I suggest above but, if it times out, we could say: "Tried to set to IPV6 and it did not work" or something of sorts.
Based on #8281, I think the best option is likely to add a timeout around the whole command.
@josevalim I am interested in taking a shot at this if work on it hasn't already started.
I see that there aren't any unit tests for the public function (Mix.Utils.read_path\2) that calls this piece of code. Do you have any suggestions for how to write a test for this case?
Thanks
@mhanberg since it needs the network, it is a bit tricky to test it. We could maybe start a tiny httpd server that serves some files but I am not sure if this is desirable.
That's what I was thinking, I'll see what I can do, thanks!
Hm, I think I have something similar on my machine.
mix local.hex --force doesn鈥檛 work. It just hangs. I investigated a bit further and this:
> :inets.start
> :ssl.start
> :httpc.request 'https://elixir-lang.org'
which runs perfectly on my other machines hangs and doesn鈥檛 return anything on that machine.
elixir --info returns this:
Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:13:13] [ds:13:13:10] [async-threads:1] [hipe]
Elixir 1.7.3 (compiled with Erlang/OTP 20)
Sadly :httpc.set_option(:ipfamily, :inet6fb4, :mix) doesn't help and it looks like ipv6 is working properly because ping6 and curl -6 are both returning correct output.
Downgrading to this makes it work again on that machine:
Erlang/OTP 20 [erts-9.3.3.3] [source] [64-bit] [smp:13:13] [ds:13:13:10] [async-threads:10] [hipe] [kernel-poll:false]
Elixir 1.6.6 (compiled with OTP 19)
I have checked and in OTP21 the :httpc.set_option(:ipfamily, :inet6fb4, :mix) is deprecated, so i will go ahead and remove it, but I still think we should wrap the whole read_path operation in a task and give the user a reasonable error message in cases of timeout. :)
@josevalim, i have similar problem. When do you intend to include this fix in stable version?
@DmitryKK it will be in the next release, coming in two months. :)
Closing in favor of #8394.
And now mix does not use IPv6 ? ;(
It seems that mix does not work without ipv4 anymore. The current flags disable/not enable the use of ipv6 sockets. Erlang 22.
Most helpful comment
Root-cause is that ipv6 is misconfigured on the machine.
Adding the following to sysctl fixed it:
Possible solutions: Add a timeouts around calls to
:httpc(orread_httpc) to indicate a misconfiguration to the user, and/or auto retry without ipv6/ipv4 fallback.