elixir-lang/elixir

iex forgets bindings when interrupted

Closed this issue · 5 comments

juped commented

Elixir and Erlang/OTP versions

Erlang/OTP 27 [erts-15.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]

Elixir 1.17.3 (compiled with Erlang/OTP 27)

Operating system

Linux 6.12.1_1 #1 SMP PREEMPT_DYNAMIC Sun Nov 24 23:14:58 UTC 2024 x86_64 GNU/Linux

Current behavior

iex forgets bindings when interrupted (via i from the ^G menu):


Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = 123
123
iex(2)> a
123
iex(3)> f = fn f -> f.(f) end
#Function<42.39164016/1 in :erl_eval.expr/6>
iex(4)> f.(f)

User switch command (type h for help)
 --> i 1

 --> c 1

** (EXIT) interrupted

Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(4)> a
error: undefined variable "a"
└─ iex:4

** (CompileError) cannot compile code (errors have been logged)

iex(4)> 

Expected behavior

I had assumed this would not happen, because it does not in erl:

Erlang/OTP 27 [erts-15.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]

Eshell V15.1.1 (press Ctrl+G to abort, type help(). for help)
1> A = 123.
123
2> A.
123
3> F = fun(F) -> F(F) end.
#Fun<erl_eval.42.39164016>
4> F(F).

User switch command (type h for help)
 --> i 1

 --> c 1

** exception exit: killed
5> A.
123
6> 

This does not appear to be filed as an open or closed issue anywhere, so I am filing it now.

Thank you for the report. Unfortunately I cannot reproduce it:

Screenshot 2024-12-05 at 14 25 32

I wonder why a new session is starting up in your case. 🤔 How are you starting IEx?

juped commented

Just iex from the terminal.

The infinite loop is important. If you're not actually interrupting anything with your interrupt, it won't happen, as you show above.

I don't really know anything about how iex is put together at runtime, but you lose binds, imports, probably other environmental things.

Oh, of course, the loop being required makes sense. Thank you!

Yeah, I see why it works in Erlang, they automatically spawn a new process:

Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
1> A = 123.
123
2> self().
<0.88.0>
3> self().
<0.88.0>
4>  F = fun(F) -> F(F) end.
#Fun<erl_eval.42.39164016>
5> F(F).

User switch command (type h for help)
 --> i 1

 --> c 1

** exception exit: killed
6> self().
<0.94.0>

In Elixir, we decided that changing the process behind the scenes would be surprising behaviour. Things that you had set up, such as monitors, messages, or links, will either be broken or missing. So I am not sure we want to make this trade-off here too. :(

I will close this for now, glad to reopen if people feel strongly and have good arguments, but I think the safest is to keep the evlauation tied to the process. Thanks for the report!