Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vim running into infinite loop if stdin closed when process stucked because of busy IO #3729

Open
clan opened this issue Dec 28, 2018 · 0 comments

Comments

@clan
Copy link

clan commented Dec 28, 2018

We've found vim (vim-8.0.1298) running into infinite loop several times.

VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Apr 23 2018 22:39:41)

On a server with very busy IO:

  1. open a large file with vim, do some edit
  2. save this file with ":w", then vim will be stucked (for a long time, because of the busy IO)
  3. do some random operations (unknown yet, :-( )
  4. before vim return, kill the shell where vim called from,
  5. check from another shell, this vim process will run into an infinite loop

lsof -n -p shows

# lsof -n -p 6738
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
.....
vim 6738 root 0u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
vim 6738 root 1u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
vim 6738 root 2u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
vim 6738 root 3u REG 254,2 324237950976 46285205 /home/.api2.swp (deleted)

strace -fp can see following syscall repeated.

select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 1 (in [0], left {tv_sec=0, tv_usec=0})
read(0, "", 4096) = 0
select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 1 (in [0], left {tv_sec=0, tv_usec=0})
read(0, "", 4096) = 0
mmap(NULL, 51519488, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9672456000
munmap(0x7f966f334000, 51519488) = 0
select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 1 (in [0], left {tv_sec=0, tv_usec=0})
read(0, "", 4096) = 0
select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 1 (in [0], left {tv_sec=0, tv_usec=0})
read(0, "", 4096) = 0

read from 0 (stdin) return 0 mean stdin is closed. This can be confirmed from lsof.

gdb w/ break on read, following is the stack:

(gdb) where
#0 __libc_read (fd=0, buf=0x8787d0 , nbytes=4096) at ../sysdeps/unix/sysv/linux/read.c:25
#1 0x00000000005a1952 in fill_input_buf (exit_on_error=0) at ui.c:1827
#2 0x000000000059f977 in ui_breakcheck_force (force=0) at ui.c:376
#3 ui_breakcheck () at ui.c:356
#4 0x0000000000494d05 in vgetorpeek (advance=1) at getchar.c:2048
#5 0x0000000000494284 in vgetc () at getchar.c:1612
#6 0x0000000000495ba5 in safe_vgetc () at getchar.c:1808
#7 plain_vgetc () at getchar.c:1825
#8 0x0000000000422103 in bracketed_paste (mode=PASTE_INSERT, drop=0, gap=0x0) at edit.c:9521
#9 0x000000000041f326 in edit (cmdchar=, startln=, count=0) at edit.c:1212
#10 0x00000000004de643 in invoke_edit (cap=, repl=0, cmd=, startln=0) at normal.c:9182
#11 nv_edit (cap=0x7fffb1fe6610) at normal.c:9152
#12 0x00000000004d7aa6 in normal_cmd (oap=0x7fffb1fe66b0, toplevel=1) at normal.c:1150
#13 0x00000000005e12cd in main_loop (cmdwin=0, noexmode=0) at main.c:1357
#14 0x00000000005e088a in vim_main2 () at main.c:905
#15 0x00000000005df2e2 in main (argc=, argv=) at main.c:429

after some analysis, it seems function fill_input_buf() at ui.c still return normaly if read return 0 (len) and got_int (confirmed in gdb) is true.

1865 if (len <= 0 && !got_int)
1866 read_error_exit();
1867 if (len > 0)
1868 did_read_something = TRUE;
1869 if (got_int)
1870 {
1871 /* Interrupted, pretend a CTRL-C was typed. */
1872 inbuf[0] = 3;
1873 inbufcount = 1;
1874 }

Currently, I've no idea to fix this problem and it's hard to reproduce it by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant