Dear Maintainer,
$ iex
Erlang/OTP 27 [erts-15.2.7.3] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.18.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [123,124]
~c"{|"
iex(2)>
if I EOF by ^D here, nothing happens, and ^C shows an error;
only ^\ actually quits (but the process doesn't even succumb to it so
the prompt positioning is messed up because it doesn't output a final newline).
This is clearly wrong, especially given:
$ cat | iex
Erlang/OTP 27 [erts-15.2.7.3] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.18.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [123,124]
~c"{|"
iex(2)>
and EOFing here actually registers
(though it doesn't emit a final newline either so the prompt is also messed up),
and
$ iex < /dev/null
Erlang/OTP 27 [erts-15.2.7.3] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.18.3) - press Ctrl+C to exit (type h() ENTER for help)
$
strace of iex when getting ^D:
[pid 2539937] ppoll([{fd=10<pipe:[760177565]>, events=POLLIN|POLLRDNORM}], 1, NULL, NULL, 8 <unfinished ...>
[pid 2539938] <... epoll_wait resumed>[{events=EPOLLIN, data={u32=0, u64=140179142606848}}], 512, -1) = 1
[pid 2539938] epoll_wait(4<anon_inode:[eventpoll]>, <unfinished ...>
[pid 2539932] read(0</dev/pts/5>, "\4", 1024) = 1
[pid 2539932] epoll_ctl(4<anon_inode:[eventpoll]>, EPOLL_CTL_MOD, 0</dev/pts/5>, {events=EPOLLIN|EPOLLONESHOT, data={u32=0, u64=0}}) = 0
[pid 2539932] writev(1</dev/pts/5>, [{iov_base="\7", iov_len=1}], 1) = 1
strace of cat | iex:
[pid 2550516] ppoll([{fd=10<pipe:[760201449]>, events=POLLIN|POLLRDNORM}], 1, NULL, NULL, 8 <unfinished ...>
[pid 2550424] <... epoll_wait resumed>[{events=EPOLLIN, data={u32=9, u64=16148037947227111433}}], 512, -1) = 1
[pid 2550424] timerfd_settime(9<anon_inode:[timerfd]>, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=0, tv_nsec=0}}, NULL) = 0
[pid 2550424] timerfd_settime(9<anon_inode:[timerfd]>, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=12, tv_nsec=58194701}}, NULL) = 0
[pid 2550424] epoll_wait(6<anon_inode:[eventpoll]>, <unfinished ...>
[pid 2550517] <... epoll_wait resumed>[{events=EPOLLHUP, data={u32=0, u64=139693811302400}}], 512, -1) = 1
[pid 2550517] epoll_wait(4<anon_inode:[eventpoll]>, <unfinished ...>
[pid 2550510] read(0<pipe:[760194369]>, "", 1024) = 0
[pid 2550416] epoll_ctl(4<anon_inode:[eventpoll]>, EPOLL_CTL_DEL, 0<pipe:[760194369]>, 0x7f0d07d12474) = 0
[pid 2550416] epoll_ctl(4<anon_inode:[eventpoll]>, EPOLL_CTL_DEL, 17<pipe:[760192190]>, 0x7f0d07d12474) = 0
[pid 2550416] close(17<pipe:[760192190]>) = 0
[pid 2550416] close(18<pipe:[760192190]>) = 0
[pid 2550416] rt_sigaction(SIGCONT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f0d543c2df0}, {sa_handler=0x55892f297a30, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK, sa_restorer=0x7f0d543c2df0}, 8) = 0
[pid 2550416] rt_sigaction(SIGWINCH, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f0d543c2df0}, {sa_handler=0x55892f2979e0, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK, sa_restorer=0x7f0d543c2df0}, 8) = 0
[pid 2550416] write(8<pipe:[760201448]>, "!", 1) = 1
This implies that iex puts its input teletype into -icanon -echo mode,
which is easy to confirm:
$ stty -F /dev/pts/5
speed 38400 baud; line = 0;
min = 1; time = 0;
-brkint -icrnl -imaxbel iutf8
-opost
-icanon -echo
Makes sense, since iex ships its own readline-style input handler
(and explains why it doesn't work that well).
iex needs to correctly understand eof/c_cc[VEOF] in its icanon emulator.
Best,