Repository: neovim
Issue: feedkeys(.., 'x!') causes nvim to exit when stdin is /dev/null
Labels: bug,input

- `nvim --version`: 0.2.0
- Vim (version: ) behaves differently? 8.0.0197
- Operating system/version: Debian GNU/Linux

### Actual behaviour
`call feedkeys('a', 'x!')`, in `Test_cursorhold_insert`, causes nvim to exit when stdin is `/dev/null`.

<details>
<summary>Stack trace when <code>read_error_exit()</code>is called</summary>

```
(gdb) bt
#0  os_inchar (buf=buf@entry=0x7ffff5507f3a "", maxlen=maxlen@entry=71, ms=ms@entry=0, tb_change_cnt=tb_change_cnt@entry=9) at ./src/nvim/os/input.c:137
#1  0x00005555556672c4 in inchar (buf=0x7ffff5507f3a "", maxlen=215, wait_time=0, tb_change_cnt=9)at ./src/nvim/getchar.c:2423
#2  0x00005555556690d1 in vgetorpeek (advance=0) at ./src/nvim/getchar.c:2243
#3  0x000055555566a160 in char_avail () at ./src/nvim/getchar.c:1567
#4  0x00005555555d575c in insert_check (state=0x7fffffff9570) at ./src/nvim/edit.c:540
#5  0x0000555555741f8b in state_enter (s=s@entry=0x7fffffff9570) at ./src/nvim/state.c:25
#6  0x00005555555d61c0 in insert_enter (s=0x7fffffff9570) at ./src/nvim/edit.c:458
#7  edit (cmdchar=<optimized out>, startln=<optimized out>, count=1) at ./src/nvim/edit.c:1335
#8  0x00005555556a9010 in invoke_edit (repl=<optimized out>, cmd=<optimized out>, startln=<optimized out>, cap=<optimized out>, cap=<optimized out>) at ./src/nvim/normal.c:7520
#9  0x00005555556b5157 in normal_execute (state=state@entry=0x7fffffff9690, key=<optimized out>) at ./src/nvim/normal.c:1137
#10 0x00005555556b6166 in normal_cmd (oap=oap@entry=0x7fffffff97d0, toplevel=toplevel@entry=true) at ./src/nvim/normal.c:7935
#11 0x0000555555636e06 in exec_normal (was_typed=was_typed@entry=true) at ./src/nvim/ex_docmd.c:8166
#12 0x00005555555bc78a in nvim_feedkeys (keys=..., mode=..., escape_csi=escape_csi@entry=true) at ./src/nvim/api/vim.c:114
#13 0x00005555555ef916 in f_feedkeys (argvars=0x7fffffff9be0, rettv=<optimized out>, fptr=<optimized out>) at ./src/nvim/eval.c:8252
#14 0x00005555555fae6f in call_func (funcname=funcname@entry=0x7ffff550c3c0 "feedkeys", len=len@entry=8, rettv=rettv@entry=0x7fffffff9df0, argcount_in=argcount_in@entry=2, argvars_in=argvars_in@entry=0x7fffffff9be0, argv_func=argv_func@entry=0x0, firstline=1, lastline=1, doesrange=0x7fffffff9ddc, evaluate=true, partial=0x0, selfdict_in=0x0) at ./src/nvim/eval.c:6389
#15 0x00005555555ffbcf in get_func_tv (name=name@entry=0x7ffff550c3c0 "feedkeys", len=8, rettv=rettv@entry=0x7fffffff9df0, arg=arg@entry=0x7fffffff9de0, firstline=firstline@entry=1, lastline=lastline@entry=1, doesrange=0x7fffffff9ddc, evaluate=1, partial=0x0, selfdict=0x0) at ./src/nvim/eval.c:6129
#16 0x0000555555604567 in ex_call (eap=0x7fffffffa030) at ./src/nvim/eval.c:2760
#17 0x0000555555639694 in do_one_cmd (cookie=0x7ffff54d5800, fgetline=0x5555555fc6c0 <get_func_line>, cstack=0x7fffffffa1c0, flags=7, cmdlinep=0x7fffffff9f80) at ./src/nvim/ex_docmd.c:2240
#18 do_cmdline (cmdline=cmdline@entry=0x0, fgetline=fgetline@entry=0x5555555fc6c0 <get_func_line>,cookie=cookie@entry=0x7ffff54d5800, flags=flags@entry=7) at ./src/nvim/ex_docmd.c:606
#19 0x00005555555f9fdc in call_user_func (fp=fp@entry=0x7ffff5444480, argcount=argcount@entry=0, argvars=argvars@entry=0x7fffffffacf0, rettv=rettv@entry=0x7fffffffaf00, firstline=firstline@entry=1,lastline=lastline@entry=1, selfdict=<optimized out>) at ./src/nvim/eval.c:21089
#20 0x00005555555fab67 in call_func (funcname=funcname@entry=0x7ffff5534480 "Test_cursorhold_insert", len=len@entry=22, rettv=rettv@entry=0x7fffffffaf00, argcount_in=argcount_in@entry=0, argvars_in=argvars_in@entry=0x7fffffffacf0, argv_func=argv_func@entry=0x0, firstline=1, lastline=1, doesrange=0x7fffffffaeec, evaluate=true, partial=0x0, selfdict_in=0x0) at ./src/nvim/eval.c:6374
#21 0x00005555555ffbcf in get_func_tv (name=name@entry=0x7ffff5534480 "Test_cursorhold_insert", len=22, rettv=rettv@entry=0x7fffffffaf00, arg=arg@entry=0x7fffffffaef0, firstline=firstline@entry=1, lastline=lastline@entry=1, doesrange=0x7fffffffaeec, evaluate=1, partial=0x0, selfdict=0x0) at ./src/nvim/eval.c:6129
#22 0x0000555555604567 in ex_call (eap=0x7fffffffb140) at ./src/nvim/eval.c:2760
#23 0x0000555555639694 in do_one_cmd (cookie=0x7ffff54d5000, fgetline=0x5555555fc6c0 <get_func_line>, cstack=0x7fffffffb2d0, flags=3, cmdlinep=0x7fffffffb090) at ./src/nvim/ex_docmd.c:2240
#24 do_cmdline (cmdline=<optimized out>, fgetline=0x5555555fc6c0 <get_func_line>, cookie=0x7ffff54d5000, flags=flags@entry=3) at ./src/nvim/ex_docmd.c:606
#25 0x0000555555602f04 in ex_execute (eap=0x7fffffffba90) at ./src/nvim/eval.c:19302
#26 0x0000555555639694 in do_one_cmd (cookie=0x7ffff54d5000, fgetline=0x5555555fc6c0 <get_func_line>, cstack=0x7fffffffbc20, flags=7, cmdlinep=0x7fffffffb9e0) at ./src/nvim/ex_docmd.c:2240
#27 do_cmdline (cmdline=cmdline@entry=0x0, fgetline=fgetline@entry=0x5555555fc6c0 <get_func_line>,cookie=cookie@entry=0x7ffff54d5000, flags=flags@entry=7) at ./src/nvim/ex_docmd.c:606
#28 0x00005555555f9fdc in call_user_func (fp=fp@entry=0x7ffff5501240, argcount=argcount@entry=1, argvars=argvars@entry=0x7fffffffc750, rettv=rettv@entry=0x7fffffffc960, firstline=firstline@entry=1,lastline=lastline@entry=1, selfdict=<optimized out>) at ./src/nvim/eval.c:21089
#29 0x00005555555fab67 in call_func (funcname=funcname@entry=0x7ffff550c200 "RunTheTest", len=len@entry=10, rettv=rettv@entry=0x7fffffffc960, argcount_in=argcount_in@entry=1, argvars_in=argvars_in@entry=0x7fffffffc750, argv_func=argv_func@entry=0x0, firstline=1, lastline=1, doesrange=0x7fffffffc94c, evaluate=true, partial=0x0, selfdict_in=0x0) at ./src/nvim/eval.c:6374
#30 0x00005555555ffbcf in get_func_tv (name=name@entry=0x7ffff550c200 "RunTheTest", len=10, rettv=rettv@entry=0x7fffffffc960, arg=arg@entry=0x7fffffffc950, firstline=firstline@entry=1, lastline=lastline@entry=1, doesrange=0x7fffffffc94c, evaluate=1, partial=0x0, selfdict=0x0) at ./src/nvim/eval.c:6129
#31 0x0000555555604567 in ex_call (eap=0x7fffffffcba0) at ./src/nvim/eval.c:2760
#32 0x0000555555639694 in do_one_cmd (cookie=0x7fffffffcb40, fgetline=0x555555631c60 <get_loop_line>, cstack=0x7fffffffcd30, flags=7, cmdlinep=0x7fffffffcaf0) at ./src/nvim/ex_docmd.c:2240
#33 do_cmdline (cmdline=cmdline@entry=0x7ffff54cf400 "\" This script is sourced while editing the .vim file with the tests.", fgetline=fgetline@entry=0x55555562cc90 <getsourceline>, cookie=cookie@entry=0x7fffffffd310, flags=flags@entry=7) at ./src/nvim/ex_docmd.c:606
#34 0x000055555562d2e6 in do_source (fname=fname@entry=0x7ffff5437ba3 "runtest.vim", check_other=check_other@entry=0, is_vimrc=is_vimrc@entry=0) at ./src/nvim/ex_cmds2.c:2935
#35 0x000055555562dd4c in cmd_source (fname=0x7ffff5437ba3 "runtest.vim", eap=<optimized out>) at ./src/nvim/ex_cmds2.c:2680
#36 0x0000555555639694 in do_one_cmd (cookie=0x0, fgetline=0x0, cstack=0x7fffffffd710, flags=10, cmdlinep=0x7fffffffd4d0) at ./src/nvim/ex_docmd.c:2240
#37 do_cmdline (cmdline=<optimized out>, fgetline=0x0, cookie=0x0, flags=10) at ./src/nvim/ex_docmd.c:606
#38 0x00005555555ac576 in exe_commands (parmp=0x7fffffffdce0) at ./src/nvim/main.c:1633
#39 main (argc=<optimized out>, argv=<optimized out>) at ./src/nvim/main.c:508
```

</details>

### Expected behaviour
nvim gracefully handles getting EOF from stdin (common during testing).

### Steps to reproduce using `nvim -u NORC`

```
make -B -C src/nvim/testdir test_autocmd.res </dev/null
```

I'm always able to reproduce this when building Neovim inside of [sbuild], which is preventing me from uploading 0.2.0 to Debian.  When manually trying to reproduce it using the above make command, it works fine on some systems but fails on others.  Not quite sure why, on some systems, it fails in sbuild but works manually.

Vim has some [code] to handle a similar situation, but in that case it's calling `fill_input_buf(FALSE);` which causes it to return from the function before calling `read_error_exit();`.

[sbuild]: https://wiki.debian.org/sbuild
[code]: https://github.com/vim/vim/blob/2a0b06def49198aef45ef173f524a638a700f9c9/src/ui.c#L1855-L1878