Hi, I'm using `read` in `zshexit` and when my terminal crashes (e.g. XTerm gets killed or ssh connection dies) Zsh spins in an endless loop until I kill it with SIGKILL (SIGTERM doesn't work). ``` zshexit() { if [[ ${#${(M)${(f)"$(</proc/self/mountinfo)"}#*/ / rw,}} == 1 ]] then if read -rq junk"?Root filesystem is still read-write. Remount ro? (y/N) " then echo mount -o remount,ro / || sleep 4 else echo fi fi } ``` Here's a backtrace: ``` #0 0x00007fb6d84eda5d in sigprocmask () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00005643fcc03d83 in signal_unblock (set=...) at ../../Src/signals.c:274 #2 0x00007fb6d7fcee1a in raw_getbyte (full=0, cptr=0x7fff401336af "", do_keytmout=0) at ../../../Src/Zle/zle_main.c:844 #3 getbyte (do_keytmout=0, timeout=0x0, full=full@entry=0) at ../../../Src/Zle/zle_main.c:880 #4 0x00007fb6d7fd22ad in zle_main_entry (cmd=<optimized out>, ap=<optimized out>) at ../../../Src/Zle/zle_main.c:2142 #5 0x00005643fcbcbcb8 in zleentry (cmd=7) at ../../Src/init.c:1604 #6 0x00005643fcb9e9c8 in bin_read (name=<optimized out>, args=<optimized out>, ops=<optimized out>, func=<optimized out>) at ../../Src/builtin.c:6408 #7 0x00005643fcba013d in execbuiltin (args=<optimized out>, assigns=<optimized out>, bn=<optimized out>) at ../../Src/builtin.c:507 #8 0x00005643fcbb0b02 in execcmd_exec (state=state@entry=0x7fff40138420, eparams=eparams@entry=0x7fff401351a0, input=input@entry=0, output=output@entry=0, how=<optimized out>, how@entry=18, last1=<optimized out>, last1@entry=2, close_if_forked=-1) at ../../Src/exec.c:4090 #9 0x00005643fcbb105f in execpline2 (state=state@entry=0x7fff40138420, pcode=<optimized out>, how=how@entry=18, input=0, output=0, last1=last1@entry=0) at ../../Src/exec.c:1927 #10 0x00005643fcbb1400 in execpline (state=state@entry=0x7fff40138420, slcode=<optimized out>, how=how@entry=18, last1=0) at ../../Src/exec.c:1658 #11 0x00005643fcbb2d60 in execlist (state=state@entry=0x7fff40138420, dont_change_job=dont_change_job@entry=1, exiting=exiting@entry=0) at ../../Src/exec.c:1413 #12 0x00005643fcbd92bc in execif (state=0x7fff40138420, do_exec=0) at ../../Src/loop.c:555 #13 0x00005643fcbaf96c in execcmd_exec (state=state@entry=0x7fff40138420, eparams=eparams@entry=0x7fff40136900, input=input@entry=0, output=output@entry=0, how=<optimized out>, how@entry=18, last1=<optimized out>, last1@entry=2, close_if_forked=-1) at ../../Src/exec.c:3910 #14 0x00005643fcbb105f in execpline2 (state=state@entry=0x7fff40138420, pcode=<optimized out>, how=how@entry=18, input=0, output=0, last1=last1@entry=0) at ../../Src/exec.c:1927 #15 0x00005643fcbb1400 in execpline (state=state@entry=0x7fff40138420, slcode=<optimized out>, how=how@entry=18, last1=0) at ../../Src/exec.c:1658 #16 0x00005643fcbb2d60 in execlist (state=state@entry=0x7fff40138420, dont_change_job=dont_change_job@entry=1, exiting=exiting@entry=0) at ../../Src/exec.c:1413 #17 0x00005643fcbd92f8 in execif (state=0x7fff40138420, do_exec=0) at ../../Src/loop.c:576 #18 0x00005643fcbaf96c in execcmd_exec (state=state@entry=0x7fff40138420, eparams=eparams@entry=0x7fff40138060, input=input@entry=0, output=output@entry=0, how=<optimized out>, how@entry=18, last1=<optimized out>, last1@entry=2, close_if_forked=-1) at ../../Src/exec.c:3910 #19 0x00005643fcbb105f in execpline2 (state=state@entry=0x7fff40138420, pcode=<optimized out>, how=how@entry=18, input=0, output=0, last1=last1@entry=0) at ../../Src/exec.c:1927 #20 0x00005643fcbb1400 in execpline (state=state@entry=0x7fff40138420, slcode=<optimized out>, how=how@entry=18, last1=0) at ../../Src/exec.c:1658 #21 0x00005643fcbb2d60 in execlist (state=state@entry=0x7fff40138420, dont_change_job=dont_change_job@entry=1, exiting=exiting@entry=0) at ../../Src/exec.c:1413 #22 0x00005643fcbb3202 in execode (p=p@entry=0x5643fd1b2270, dont_change_job=dont_change_job@entry=1, exiting=exiting@entry=0, context=context@entry=0x5643fcc24b8d "shfunc") at ../../Src/exec.c:1192 #23 0x00005643fcbb40ab in runshfunc (prog=0x5643fd1b2270, wrap=0x0, name=0x7fb6d8003170 "zshexit") at ../../Src/exec.c:5974 #24 0x00005643fcbb45d6 in doshfunc (shfunc=0x5643fd1ccea0, doshargs=doshargs@entry=0x0, noreturnval=noreturnval@entry=1) at ../../Src/exec.c:5824 #25 0x00005643fcc17a43 in callhookfunc (name=0x5643fcc23818 "zshexit", lnklst=0x0, arrayp=1, retval=0x0) at ../../Src/utils.c:1530 #26 0x00005643fcba6095 in zexit (val=<optimized out>, from_where=<optimized out>) at ../../Src/builtin.c:5810 #27 0x00007fb6d7fcecb4 in getbyte (do_keytmout=do_keytmout@entry=0, timeout=timeout@entry=0x0, full=full@entry=1) at ../../../Src/Zle/zle_main.c:904 #28 0x00007fb6d7fcdbc3 in getkeybuf (w=<optimized out>) at ../../../Src/Zle/zle_keymap.c:1676 #29 getkeymapcmd (km=0x5643fd1900f0, funcp=funcp@entry=0x7fff40138c68, strp=strp@entry=0x7fff40138c70) at ../../../Src/Zle/zle_keymap.c:1587 #30 0x00007fb6d7fcddae in getkeycmd () at ../../../Src/Zle/zle_keymap.c:1715 #31 0x00007fb6d7fcfed5 in zlecore () at ../../../Src/Zle/zle_main.c:1124 #32 0x00007fb6d7fd0dd0 in zleread (lp=<optimized out>, rp=<optimized out>, flags=<optimized out>, context=0, init=0x7fb6d7ff041d "zle-line-init", finish=0x7fb6d7ff040d "zle-line-finish") at ../../../Src/Zle/zle_main.c:1347 #33 0x00005643fcbcbcb8 in zleentry (cmd=cmd@entry=1) at ../../Src/init.c:1604 #34 0x00005643fcbcd209 in inputline () at ../../Src/input.c:295 #35 ingetc () at ../../Src/input.c:228 #36 0x00005643fcbcd37f in ingetc () at ../../Src/input.c:196 #37 0x00005643fcbc4e66 in ihgetc () at ../../Src/hist.c:407 #38 0x00005643fcbd6a9e in gettok () at ../../Src/lex.c:611 #39 zshlex () at ../../Src/lex.c:275 #40 0x00005643fcbd787e in zshlex () at ../../Src/lex.c:268 #41 0x00005643fcbf6776 in parse_event (endtok=endtok@entry=37) at ../../Src/parse.c:581 #42 0x00005643fcbc8545 in loop (toplevel=toplevel@entry=1, justonce=justonce@entry=0) at ../../Src/init.c:147 #43 0x00005643fcbcc2c6 in zsh_main (argc=<optimized out>, argv=<optimized out>) at ../../Src/init.c:1758 #44 0x00007fb6d84da09b in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6 #45 0x00005643fcb90d4a in _start () ``` Looking into `getbyte` in zle_main.c there's this code: ```c r = raw_getbyte(do_keytmout, &cc, full); … if (r == 0) { /* The test for IGNOREEOF was added to make zsh ignore ^Ds that were typed while commands are running. Unfortunately this caused trouble under at least one system (SunOS 4.1). Here shells that lost their xterm (e.g. if it was killed with -9) didn't fail to read from the terminal but instead happily continued to read EOFs, so that the above read returned with 0, and, with IGNOREEOF set, this caused an infinite loop. The simple way around this was to add the counter (icnt) so that this happens 20 times and than the shell gives up (yes, this is a bit dirty...). */ if ((zlereadflags & ZLRF_IGNOREEOF) && icnt++ < 20) continue; stopmsg = 1; zexit(1, ZEXIT_NORMAL); } ``` So, if `raw_getbyte` returns `0` `zexit` gets called again. I think this causes the loop. I didn't debug a hanging process. I've got the backtrace from a core dump. Regards Jörg -- Jeder macht, was er will – Keiner macht was er soll – Aber alle machen mit!
Attachment:
signature.asc
Description: PGP signature