* Where to start debugging zle recursive-edit? / Ctrl-C @ 2016-09-23 16:26 Sebastian Gniazdowski 2016-09-24 20:31 ` Bart Schaefer 0 siblings, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-23 16:26 UTC (permalink / raw) To: Zsh hackers list Hello, I use a POSTDISPLAY interface for Ctrl-R, that works inside .zle-recursive edit. Occurring problems with Ctrl-C every day. Some limited response, not instant cancel of search, once even full blockade of interruption. Funny that it became much more intensive after adding few custom keymap's bindings for left/right cursors, page up/page down keys. Also one user reports that Ctrl-C crashes Zsh. Would add a debug print somewhere and observe, then extend the debugging. But where? Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-23 16:26 Where to start debugging zle recursive-edit? / Ctrl-C Sebastian Gniazdowski @ 2016-09-24 20:31 ` Bart Schaefer 2016-09-24 20:58 ` Sebastian Gniazdowski ` (3 more replies) 0 siblings, 4 replies; 21+ messages in thread From: Bart Schaefer @ 2016-09-24 20:31 UTC (permalink / raw) To: Zsh hackers list On Sep 23, 6:26pm, Sebastian Gniazdowski wrote: } } I use a POSTDISPLAY interface for Ctrl-R, that works inside } .zle-recursive edit. Occurring problems with Ctrl-C every day. } [...] Funny that it became much more intensive after adding } few custom keymap's bindings for left/right cursors This probably means that the ^C is arriving while zle is waiting to see if a binding has multiple "keystrokes" before determining what widget to call. Does emacs mode vs. viins or vicmd matter? Does (un)setopt multibyte? } Also one user reports that Ctrl-C crashes Zsh. If this is with the latest build from git, it might be related to the recently-introduced signal-handling problem with functions that Daniel and I have been discussing elsewhere. } Would add a debug print somewhere and observe, then extend the } debugging. But where? You're probably interested in getbyte() in zle_main.c, but you might also attach with a debugger and put a breakpoint in zhandler so you can get a stack trace of where the handler is being called [if it is]. (Starting the debugger first and running zsh inside it won't work as well because the debugger itself will trap the signals). ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-24 20:31 ` Bart Schaefer @ 2016-09-24 20:58 ` Sebastian Gniazdowski 2016-09-25 7:09 ` Daniel Shahaf 2016-09-26 22:16 ` Sebastian Gniazdowski ` (2 subsequent siblings) 3 siblings, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-24 20:58 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 24 September 2016 at 22:31, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Sep 23, 6:26pm, Sebastian Gniazdowski wrote: > } > } I use a POSTDISPLAY interface for Ctrl-R, that works inside > } .zle-recursive edit. Occurring problems with Ctrl-C every day. > } [...] Funny that it became much more intensive after adding > } few custom keymap's bindings for left/right cursors > > This probably means that the ^C is arriving while zle is waiting > to see if a binding has multiple "keystrokes" before determining > what widget to call. That would explain what at first glance looks surprising. > Does emacs mode vs. viins or vicmd matter? Does (un)setopt multibyte? I create custom keymap from emac's: https://github.com/psprint/history-search-multi-word/blob/master/history-search-multi-word#L155 Rather hard to test viins and vicmd? Might try with multibyte when I spot this happening and repeating. And one session now had this. Doing unsetopt multibyte stopped this, restoring the option didn't cause the issue to come back. > } Also one user reports that Ctrl-C crashes Zsh. > > If this is with the latest build from git, it might be related to > the recently-introduced signal-handling problem with functions that > Daniel and I have been discussing elsewhere. It's 5.1.1, and I've tested rather identical setup in coincidence: https://github.com/psprint/history-search-multi-word/issues/2 Proposed a possible fix but user didn't respond if it helped: - bindkey -N zhcw main + bindkey -N zhcw emacs > } Would add a debug print somewhere and observe, then extend the > } debugging. But where? > > You're probably interested in getbyte() in zle_main.c, but you might > also attach with a debugger and put a breakpoint in zhandler so you > can get a stack trace of where the handler is being called [if it is]. > (Starting the debugger first and running zsh inside it won't work as > well because the debugger itself will trap the signals). Thanks, will sure get on that tomorrow. I also sometimes get crashes. Terminal window closes. Any tips for generating coredumps on OS X? I'm able to google that when will have time, but also wanted to disable -O, and ./configure --help | grep -i opt didn't show any option. Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-24 20:58 ` Sebastian Gniazdowski @ 2016-09-25 7:09 ` Daniel Shahaf 0 siblings, 0 replies; 21+ messages in thread From: Daniel Shahaf @ 2016-09-25 7:09 UTC (permalink / raw) To: Sebastian Gniazdowski; +Cc: Zsh hackers list Sebastian Gniazdowski wrote on Sat, Sep 24, 2016 at 22:58:19 +0200: > but also wanted to disable -O, and ./configure --help | grep -i opt > didn't show any option. --enable-zsh-debug does that and more. And for future reference CFLAGS=-O0 should have done it too. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-24 20:31 ` Bart Schaefer 2016-09-24 20:58 ` Sebastian Gniazdowski @ 2016-09-26 22:16 ` Sebastian Gniazdowski 2016-09-27 16:09 ` Bart Schaefer 2016-09-30 9:04 ` Sebastian Gniazdowski 2016-09-30 11:28 ` Sebastian Gniazdowski 3 siblings, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-26 22:16 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list Hello, have unoptimized HEAD Zsh, coredumps are set up, added some stressing things to zshrc: TMOUT=1 function, PERIOD=1 hook, repeat 50; do sleep 1000000 &; done, coproc cat – and I'm waiting. The issue wasn't very active in past two days and there was no good reason to start lldb. PS. Any ideas of how to stress Zsh more? Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-26 22:16 ` Sebastian Gniazdowski @ 2016-09-27 16:09 ` Bart Schaefer 2016-09-29 9:30 ` Sebastian Gniazdowski 0 siblings, 1 reply; 21+ messages in thread From: Bart Schaefer @ 2016-09-27 16:09 UTC (permalink / raw) To: Zsh hackers list On Sep 27, 12:16am, Sebastian Gniazdowski wrote: } } have unoptimized HEAD Zsh, coredumps are set up, added some stressing If you're not seeing the problem under these circumstances, then it's probably a race condition that's eliminated either by taking out the code optimization or by adding the other processing. Try first to reproduce with the minimum differences from when you were seeing it before, i.e., just debugging symbols and core dumps enabled, before you start throwing in theoretical stressors. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-27 16:09 ` Bart Schaefer @ 2016-09-29 9:30 ` Sebastian Gniazdowski 2016-09-29 17:07 ` Bart Schaefer 0 siblings, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-29 9:30 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 27 September 2016 at 18:09, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Sep 27, 12:16am, Sebastian Gniazdowski wrote: > } > } have unoptimized HEAD Zsh, coredumps are set up, added some stressing > > If you're not seeing the problem under these circumstances, then it's > probably a race condition that's eliminated either by taking out the > code optimization or by adding the other processing. It seems so, hours after I switched to CFLAGS=-O2 compiled binary, I've got a suspicious effect, after smoothly running no-opt binary for few days – couldn't recall if I spotted anything suspicious. The effect is message at shell startup: TRAPALRM: scalar parameter abcdef created globally in function TRAPALRM" It appeared just once, not long after switching to -O2. I don't use warn_create_global, and did a test that Mikael suggested to ensure: function setopt() { print -r - "$funcfiletrace[1]: $0 ${(q-)@}" >>! /tmp/setopt_data; builtin $0 "$@" } and only "setopt localoptions warncreateglobal" from z-sy-h was reported. Zshrc has at the end: TRAPALRM() { abcdef=$(( abcdef + 1 )); } TMOUT=1 PERIODIC_HOOK() { efghij=$(( efghij + 1 )); } PERIOD=1 add-zsh-hook periodic PERIODIC_HOOK repeat 50; do sleep 1000000 &; done coproc cat My aim is .recursive-edit and Ctrl-C, but just want to hook at something first, have any backtrace, I suspect it will be easy to connect with problems with .recursive-edit even when not directly related to it. Crash related to Ctrl-C appeared in uncanny situations AFAIR like Ctrl-R, Ctrl-C multiple times, then menu search completion with also Ctrl-C, something like this, hard to reproduce. Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-29 9:30 ` Sebastian Gniazdowski @ 2016-09-29 17:07 ` Bart Schaefer 0 siblings, 0 replies; 21+ messages in thread From: Bart Schaefer @ 2016-09-29 17:07 UTC (permalink / raw) To: Zsh hackers list On Sep 29, 11:30am, Sebastian Gniazdowski wrote: } Subject: Re: Where to start debugging zle recursive-edit? / Ctrl-C } } I've got a suspicious effect, after smoothly running no-opt binary for } few days - couldn't recall if I spotted anything suspicious. The } effect is message at shell startup: } } TRAPALRM: scalar parameter abcdef created globally in function TRAPALRM" } } [...] } } and only "setopt localoptions warncreateglobal" from z-sy-h was } reported. Zshrc has at the end: } } TRAPALRM() { abcdef=$(( abcdef + 1 )); } } TMOUT=1 So what's happening is that z-sy-h begins executing, and then *while* it is executing, the first TMOUT occurs and TRAPALRM executes. It therefore picks up the warncreateglobal from the z-sy-h context and so you get the warning about the assignment to abcdef. This could happen any time that z-sy-h is active simultaneously with the TMOUT alarm. } Crash related to Ctrl-C appeared in uncanny situations } AFAIR like Ctrl-R, Ctrl-C multiple times, then menu search completion } with also Ctrl-C, something like this, hard to reproduce. Memory management for menu selection is known to be somewhat fragile; other crashes have occurred there. Usually this seems to happen when tracking of where things should be drawn on the screen gets out of sync with the data structures describing what to draw, see for example workers/37961 (commit f07a1bd0). It would not surprise me to find that an ill-timed interrupt could result in the same sort of problem. There are some queue_signals() regions in complist.c but they're very narrowly defined. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-24 20:31 ` Bart Schaefer 2016-09-24 20:58 ` Sebastian Gniazdowski 2016-09-26 22:16 ` Sebastian Gniazdowski @ 2016-09-30 9:04 ` Sebastian Gniazdowski 2016-09-30 11:28 ` Sebastian Gniazdowski 3 siblings, 0 replies; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-30 9:04 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 1358 bytes --] On 24 September 2016 at 22:31, Bart Schaefer <schaefer@brasslantern.com> wrote: > You're probably interested in getbyte() in zle_main.c, but you might > also attach with a debugger and put a breakpoint in zhandler so you > can get a stack trace of where the handler is being called [if it is]. > (Starting the debugger first and running zsh inside it won't work as > well because the debugger itself will trap the signals). I've set breakpoint to zhandler, it was called on each Ctrl-C. And .recursiveedit never exited. Following execution paths I've spotted crucial places and added debug prints. Luckily it's easy to trigger ".recursiveedit not canceled" and ".rec. cancelled" paths when not in debugger. Attached is 10-context lines diff. Exit from .recursiveedit is: -- Doing break / zle_main.c: errflag: 2, retflag: 0, breaks: 0, exit_pending: 0 -- Got EINTR 1 -- Setting error in zlecore.c I've also observed that following possible, though rare: -- Got EINTR 1 -- Setting error in zlecore.c No reaction on Ctrl-C, i.e. no-exit from .recursiveedit, is: -- Trying again !errtry / zle_main.c (now another Ctrl-C) -- Doing break / zle_main.c: errflag: 2, retflag: 0, breaks: 0, exit_pending: 0 -- Got EINTR 2 -- Setting error in zlecore.c I will go further into this but apparently zhandler should set errflag? Best regards, Sebastian Gniazdowski [-- Attachment #2: rec_edit.diff.txt --] [-- Type: text/plain, Size: 3571 bytes --] diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a83d41..36884c4 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -612,28 +612,40 @@ raw_getbyte(long do_keytmout, char *cptr) tvptr = NULL; winch_unblock(); selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); winch_block(); # endif /* * Make sure a user interrupt gets passed on straight away. */ - if (selret < 0 && (errflag || retflag || breaks || exit_pending)) + if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Doing break / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); break; + } + /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first * with all fds, then try unsetting the special ones. */ if (selret < 0 && !errtry) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Trying again !errtry / zle_main.c\n" ); + fclose(_F); + errtry = 1; continue; } if (selret == 0) { /* * Nothing ready and no error, so we timed out. */ switch (tmout.tp) { case ZTM_NONE: /* keeps compiler happy if not debugging */ @@ -888,22 +900,36 @@ getbyte(long do_keytmout, int *timeout) 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, 0); } icnt = 0; if (errno == EINTR) { die = 0; + static int counter = 0; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Got EINTR %d\n", ++counter ); + fclose(_F); + if (!errflag && !retflag && !breaks && !exit_pending) + { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Continuing despite EINTR / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); continue; + } errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; } else if (errno == EWOULDBLOCK) { fcntl(0, F_SETFL, 0); } else if (errno == EIO && !die) { ret = opts[MONITOR]; opts[MONITOR] = 1; attachtty(mypgrp); @@ -1115,20 +1141,24 @@ zlecore(void) if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Setting error in zlecore.c\n" ); + fclose(_F); errflag |= ERRFLAG_ERROR; break; } redrawhook(); #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-24 20:31 ` Bart Schaefer ` (2 preceding siblings ...) 2016-09-30 9:04 ` Sebastian Gniazdowski @ 2016-09-30 11:28 ` Sebastian Gniazdowski 2016-09-30 13:30 ` Sebastian Gniazdowski 2016-09-30 21:45 ` Bart Schaefer 3 siblings, 2 replies; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-30 11:28 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 2040 bytes --] On 24 September 2016 at 22:31, Bart Schaefer <schaefer@brasslantern.com> wrote: > You're probably interested in getbyte() in zle_main.c, but you might > also attach with a debugger and put a breakpoint in zhandler so you > can get a stack trace of where the handler is being called [if it is]. > (Starting the debugger first and running zsh inside it won't work as > well because the debugger itself will trap the signals). It turned out that lldb stops at Ctrl-C even without b zhandler and this is what I've been receiving. The stack trace is at the end. But I've catched another thing. After Ctrl-C in .recursiveedit the timeouts at select() in raw_getbyte() stop occuring. Here is simple video that very well covers this. It shows debug prints stop appearing (attached 10-context lines diff). And Zconvey stops working, i.e. sched doesn't call its functions: https://asciinema.org/a/7s5dofinxlnn1i80ojunzybp7 ----------------- BT 10 / LLDB ---------------- (lldb) bt 10 * thread #1: tid = 0x1c441b, 0x00007fff897b107a libsystem_kernel.dylib`__select + 10, queue = 'com.apple.main-thread', stop reason = signal SIGINT * frame #0: 0x00007fff897b107a libsystem_kernel.dylib`__select + 10 frame #1: 0x00000001082b70e0 zle.so`raw_getbyte(do_keytmout=0, cptr="") + 640 at zle_main.c:615 frame #2: 0x00000001082b6abf zle.so`getbyte(do_keytmout=0, timeout=0x0000000000000000) + 319 at zle_main.c:893 frame #3: 0x00000001082b5798 zle.so`getkeybuf(w=0) + 24 at zle_keymap.c:1663 frame #4: 0x00000001082b54b6 zle.so`getkeymapcmd(km=0x00007fbe3201ce00, funcp=0x00007fff57c81c10, strp=0x00007fff57c81bf8) + 102 at zle_keymap.c:1581 frame #5: 0x00000001082b5903 zle.so`getkeycmd + 35 at zle_keymap.c:1692 frame #6: 0x00000001082b8430 zle.so`zlecore + 320 at zle_main.c:1136 frame #7: 0x00000001082b951b zle.so`recursiveedit(args=0x00000001083d3a00) + 27 at zle_main.c:1903 frame #8: 0x00000001082b7ea2 zle.so`execzlefunc(func=0x00000001082ea408, args=0x00000001083d3a00, set_bindk=1) + 770 at zle_main.c:1455 [-- Attachment #2: rec2_edit.2.diff.txt --] [-- Type: text/plain, Size: 4228 bytes --] diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a83d41..7f3da8d 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -612,31 +612,55 @@ raw_getbyte(long do_keytmout, char *cptr) tvptr = NULL; winch_unblock(); selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); winch_block(); # endif /* * Make sure a user interrupt gets passed on straight away. */ - if (selret < 0 && (errflag || retflag || breaks || exit_pending)) + if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Doing break / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); break; + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- NOT doing break / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); + } + /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first * with all fds, then try unsetting the special ones. */ if (selret < 0 && !errtry) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Trying again !errtry / zle_main.c\n" ); + fclose(_F); + errtry = 1; continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Passed !errtry(errtry:%d) / zle_main.c\n", errtry ); + fclose(_F); + } + if (selret == 0) { /* * Nothing ready and no error, so we timed out. */ switch (tmout.tp) { case ZTM_NONE: /* keeps compiler happy if not debugging */ #ifdef DEBUG dputs("BUG: timeout fired with no timeout set."); #endif @@ -888,22 +912,36 @@ getbyte(long do_keytmout, int *timeout) 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, 0); } icnt = 0; if (errno == EINTR) { die = 0; + static int counter = 0; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Got EINTR %d\n", ++counter ); + fclose(_F); + if (!errflag && !retflag && !breaks && !exit_pending) + { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Continuing despite EINTR / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); continue; + } errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; } else if (errno == EWOULDBLOCK) { fcntl(0, F_SETFL, 0); } else if (errno == EIO && !die) { ret = opts[MONITOR]; opts[MONITOR] = 1; attachtty(mypgrp); @@ -1115,20 +1153,24 @@ zlecore(void) if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Setting error in zlecore.c\n" ); + fclose(_F); errflag |= ERRFLAG_ERROR; break; } redrawhook(); #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 11:28 ` Sebastian Gniazdowski @ 2016-09-30 13:30 ` Sebastian Gniazdowski 2016-09-30 20:44 ` Bart Schaefer 2016-09-30 21:45 ` Bart Schaefer 1 sibling, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-30 13:30 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 1843 bytes --] On 30 September 2016 at 13:28, Sebastian Gniazdowski <sgniazdowski@gmail.com> wrote: > But I've catched another thing. After Ctrl-C in .recursiveedit the > timeouts at select() in raw_getbyte() stop occuring. Here is simple I've investigated this further. There is calc_timeout() called in the select-loop: case ZTM_MAX: /*...*/ calc_timeout(&tmout, do_keytmout); // MY DEBUG FILE *_F = fopen("/tmp/recursive.txt", "a+"); fprintf( _F, "^^^ LOOP-CALLED calc_timeout: tmout.tp == %d\n", tmout.tp ); fclose(_F); break; The calc_timeout is capable of setting tmout.tp to ZTM_NONE. I have 3 debug prints: -- tmoutp->tp <- ZTM_NONE / calc_timeout( do_keytmout: 0 ), keytimeout: 4 == CALC_TIMEOUT() one more chance (timedfns) -- CALC_TIMEOUT() !tfnode break Code of the last debug message is below: LinkNode tfnode = firstnode(timedfns); Timedfn tfdat; time_t diff, exp100ths; if (!tfnode) { // MY DEBUG FILE *_F = fopen("/tmp/recursive.txt", "a+"); fprintf( _F, "-- CALC_TIMEOUT() !tfnode break\n", tmoutp->exp100ths ); fclose(_F); break; } So, the linked list doesn't have any elements, and calc_timeout() exits with ZTM_NONE instead of ZTM_FUNC like it does all the time (so normally it executes further the for(;;) there and overwrites initial ZTM_NONE with ZTM_FUNC). This is after the lucky Ctrl-C. Wonder why no ZTM_KEY? Also, believe me, I occured 2 spontaneous stopping of timeouting right after shell started. Tried to catch this on asciinema but no luck. It looket like – few timeouts occured and then they stopped. Didn't have precise debug prints then.. Best regards, Sebastian Gniazdowski [-- Attachment #2: rec3_edit.3.diff.txt --] [-- Type: text/plain, Size: 9621 bytes --] diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a83d41..1f993fe 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -450,47 +450,82 @@ static void calc_timeout(struct ztmout *tmoutp, long do_keytmout) { if (do_keytmout && (keytimeout > 0 || do_keytmout < 0)) { if (do_keytmout < 0) tmoutp->exp100ths = (time_t)-do_keytmout; else if (keytimeout > ZMAXTIMEOUT * 100 /* 24 days for a keypress???? */) tmoutp->exp100ths = ZMAXTIMEOUT * 100; else tmoutp->exp100ths = keytimeout; tmoutp->tp = ZTM_KEY; - } else + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_KEY (%d) / calc_timeout() zle_main.c\n", tmoutp->exp100ths ); + fclose(_F); + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_NONE / calc_timeout( do_keytmout: %d ), keytimeout: %d / zle_main.c\n", do_keytmout ); + fclose(_F); + tmoutp->tp = ZTM_NONE; + } if (timedfns) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "== CALC_TIMEOUT() one more chance (timedfns)\n", tmoutp->exp100ths ); + fclose(_F); for (;;) { LinkNode tfnode = firstnode(timedfns); Timedfn tfdat; time_t diff, exp100ths; - if (!tfnode) + if (!tfnode) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() !tfnode break\n", tmoutp->exp100ths ); + fclose(_F); break; + } tfdat = (Timedfn)getdata(tfnode); diff = tfdat->when - time(NULL); + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() tfnode TRUE no break >> DIFF=%d <<\n", diff ); + fclose(_F); + if (diff < 0) { /* Already due; call it and rescan. */ tfdat->func(); continue; } if (diff > ZMAXTIMEOUT) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d > %d ZTM_MAX(%d)\n", diff, ZMAXTIMEOUT, ZTM_MAX ); + fclose(_F); + tmoutp->exp100ths = ZMAXTIMEOUT * 100; tmoutp->tp = ZTM_MAX; } else if (diff > 0) { exp100ths = diff * 100; if (tmoutp->tp != ZTM_KEY || exp100ths < tmoutp->exp100ths) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d != %d || %d < %d ZTM_FUNC(%d)\n", tmoutp->tp, ZTM_KEY, exp100ths, tmoutp->exp100ths, ZTM_FUNC ); + fclose(_F); + tmoutp->exp100ths = exp100ths; tmoutp->tp = ZTM_FUNC; } } break; } /* In case we called a function which messed up the display... */ if (resetneeded) zrefresh(); } @@ -508,20 +543,24 @@ raw_getbyte(long do_keytmout, char *cptr) struct ttyinfo ti; #endif #ifndef HAVE_POLL # ifdef HAVE_SELECT fd_set foofd, errfd; FD_ZERO(&errfd); # endif #endif calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- INIT tmout.tp(%d) ZTM_NONE(%d) ZTM_KEY(%d) / BEGIN RAW_GETBYTE() zle_main.c\n", tmout.tp, ZTM_NONE, ZTM_KEY ); + fclose(_F); /* * Handle timeouts and watched fd's. If a watched fd or a function * timeout triggers we restart any key timeout. This is likely to * be harmless: the combination is extremely rare and a function * is likely to occupy the user for a little while anyway. We used * to make timeouts take precedence, but we can't now that the * timeouts may be external, so we may have both a permanent watched * fd and a long-term timeout. */ @@ -600,43 +639,78 @@ raw_getbyte(long do_keytmout, char *cptr) if (fd > fdmax) fdmax = fd; } } FD_ZERO(&errfd); if (tmout.tp != ZTM_NONE) { expire_tv.tv_sec = tmout.exp100ths / 100; expire_tv.tv_usec = (tmout.exp100ths % 100) * 10000L; tvptr = &expire_tv; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); } - else + else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- FINAL (STOP) tmoutp == ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); + tvptr = NULL; + } winch_unblock(); selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); winch_block(); # endif /* * Make sure a user interrupt gets passed on straight away. */ - if (selret < 0 && (errflag || retflag || breaks || exit_pending)) + if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Doing break / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); break; + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- NOT doing break / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); + } + /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first * with all fds, then try unsetting the special ones. */ if (selret < 0 && !errtry) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Trying again !errtry / zle_main.c\n" ); + fclose(_F); + errtry = 1; continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Passed !errtry(errtry:%d) / zle_main.c\n", errtry ); + fclose(_F); + } + if (selret == 0) { /* * Nothing ready and no error, so we timed out. */ switch (tmout.tp) { case ZTM_NONE: /* keeps compiler happy if not debugging */ #ifdef DEBUG dputs("BUG: timeout fired with no timeout set."); #endif @@ -669,20 +743,24 @@ raw_getbyte(long do_keytmout, char *cptr) case ZTM_MAX: /* * Reached the limit of our range, but not the * actual timeout; recalculate the timeout. * We're cheating with the key timeout here: * if one clashed with a function timeout we * reconsider the key timeout from scratch. * The effect of this is microscopic. */ calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "^^^ LOOP-CALLED calc_timeout: tmout.tp == %d / zle_main.c\n", tmout.tp ); + fclose(_F); break; } /* * If we handled the timeout successfully, * carry on. */ if (selret == 0) continue; } /* If error or unhandled timeout, give up. */ @@ -888,22 +966,36 @@ getbyte(long do_keytmout, int *timeout) 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, 0); } icnt = 0; if (errno == EINTR) { die = 0; + static int counter = 0; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Got EINTR %d\n", ++counter ); + fclose(_F); + if (!errflag && !retflag && !breaks && !exit_pending) + { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Continuing despite EINTR / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); continue; + } errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; } else if (errno == EWOULDBLOCK) { fcntl(0, F_SETFL, 0); } else if (errno == EIO && !die) { ret = opts[MONITOR]; opts[MONITOR] = 1; attachtty(mypgrp); @@ -1115,20 +1207,24 @@ zlecore(void) if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Setting error in zlecore.c\n" ); + fclose(_F); errflag |= ERRFLAG_ERROR; break; } redrawhook(); #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 13:30 ` Sebastian Gniazdowski @ 2016-09-30 20:44 ` Bart Schaefer 2016-10-02 16:26 ` Sebastian Gniazdowski 2016-10-05 5:31 ` Sebastian Gniazdowski 0 siblings, 2 replies; 21+ messages in thread From: Bart Schaefer @ 2016-09-30 20:44 UTC (permalink / raw) To: Zsh hackers list On Sep 30, 3:30pm, Sebastian Gniazdowski wrote: } } So, the linked list doesn't have any elements, and calc_timeout() } exits with ZTM_NONE instead of ZTM_FUNC If I recall correctly how this is architected ... This must mean that you are interrupting the scheduled function itself, before it has a chance to execute "sched" and reset its timer. Because you are in recursive-edit, interrupting does not go all they way back to the top-level prompt where the precmd hook would restore the timer, so it remains unscheduled until the current zle session is done and precmd runs again. You may need to find a more aggressive place to reset the timer, such as in the zle-line-pre-redraw hook, or else create a wrapper widget for recursive-edit. Either way you'd want to examine $zle_scheduled_events to see if the timer is still pending, before scheduling it again. Or possibly you could switch from doing this with a timer scheduled function to using a "zle -F" handler function. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 20:44 ` Bart Schaefer @ 2016-10-02 16:26 ` Sebastian Gniazdowski 2016-10-02 17:37 ` Sebastian Gniazdowski 2016-10-05 5:31 ` Sebastian Gniazdowski 1 sibling, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-10-02 16:26 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 4029 bytes --] On 30 September 2016 at 22:44, Bart Schaefer <schaefer@brasslantern.com> wrote: > Because you are in recursive-edit, interrupting does not go all they > way back to the top-level prompt where the precmd hook would restore > the timer, so it remains unscheduled until the current zle session > is done and precmd runs again. I'm looking at the outputs from some time today and what you say seems to ring bells thinking what I observe but not yet clear. However, what I do observe clearly is: -- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c -- (**) NOT doing break selret[0] / zle_main.c: errflag: 0, retflag: 0, breaks: 0, exit_pending: 0 -- Passed !errtry(errtry:1) selret[0] / zle_main.c ## set errflag to 2 (ERRFLAG_INT:2) / signals.c This means: SIGINT is received – select breaks. Then errflag is checked (**): if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { fprintf( _F, "-- Doing break [selret:%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\> selret, errflag, retflag, breaks, exit_pending ); break; } else { fprintf( _F, "-- NOT doing break selret[%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: > selret, errflag, retflag, breaks, exit_pending ); } (fopen/fclose removed). Result: no break is done, no errflag to trigger it. Then the check runs: if (selret < 0 && !errtry) { fprintf( _F, "-- Trying again selret[%d], !errtry[%d] / zle_main.c\n", selret, errtry ); errtry = 1; continue; } else And select is run again – .recedit ignores SIGNT, does not return. This is the thing that I observe, multiple Ctrl-C to break out from widget. After this zhandler() sets the errflag: if (!handletrap(SIGINT)) { if ((isset(PRIVILEGED) || isset(RESTRICTED)) && isset(INTERACTIVE) && noerrexit < 0) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; errflag |= ERRFLAG_INT; inerrflush(); check_cursh_sig(SIGINT); fprintf( _F, "## set errflag to %d (ERRFLAG_INT:%d) / signals.c\n", errflag, ERRFLAG_INT ); } I wonder if this can result also in problems with rescheduling. Code runs with errflag set and as you said this stops scheduled function before any execution is done. Can something be done to make zhandler() set errflag faster, or to make the raw_getbyte's after-select() checks wait for zhandler's resolution? > You may need to find a more aggressive place to reset the timer, such > as in the zle-line-pre-redraw hook, or else create a wrapper widget > for recursive-edit. > > Either way you'd want to examine $zle_scheduled_events to see if the > timer is still pending, before scheduling it again. I use this trick: ZCONVEY_SCHEDULE_ORIGIN="$SECONDS" sched +"${ZCONVEY_CONFIG[check_interval]}" __zconvey_on_period_passed "$ZCONVEY_SCHEDULE_ORIGIN" Then inside the handler a check is done to make only the current "*SCHEDULE_ORIGIN" do rescheduling. So I can quite freely overschedule, in the end only last schedule goes int rescheduling loop. > > Or possibly you could switch from doing this with a timer scheduled > function to using a "zle -F" handler function. Would be great to also have in 5.3 .recedit answering predictably to Ctrl-C. What's also interesting is that I could not get setting errflag late when not in .recedit. The logs always look like this: -- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c ## set errflag to 2 (ERRFLAG_INT:2) / signals.c -- Doing break [selret:-1] / zle_main.c: errflag: 2, retflag: 0, breaks: 0, exit_pending: 0 -- Got EINTR 3 -- Setting error in zlecore.c Best regards, Sebastian Gniazdowski [-- Attachment #2: rec4_edit.4.diff.txt --] [-- Type: text/plain, Size: 11023 bytes --] diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a83d41..7bcf450 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -450,47 +450,87 @@ static void calc_timeout(struct ztmout *tmoutp, long do_keytmout) { if (do_keytmout && (keytimeout > 0 || do_keytmout < 0)) { if (do_keytmout < 0) tmoutp->exp100ths = (time_t)-do_keytmout; else if (keytimeout > ZMAXTIMEOUT * 100 /* 24 days for a keypress???? */) tmoutp->exp100ths = ZMAXTIMEOUT * 100; else tmoutp->exp100ths = keytimeout; tmoutp->tp = ZTM_KEY; - } else + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_KEY (%d) / calc_timeout() zle_main.c\n", tmoutp->exp100ths ); + fclose(_F); + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_NONE / calc_timeout( do_keytmout: %d ), keytimeout: %d / zle_main.c\n", do_keytmout, keytimeout ); + fclose(_F); + tmoutp->tp = ZTM_NONE; + } if (timedfns) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "== CALC_TIMEOUT() one more chance (timedfns exp100ths: %d)\n", tmoutp->exp100ths ); + fclose(_F); for (;;) { LinkNode tfnode = firstnode(timedfns); Timedfn tfdat; time_t diff, exp100ths; - if (!tfnode) + if (!tfnode) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() !tfnode break\n" ); + fclose(_F); break; + } tfdat = (Timedfn)getdata(tfnode); diff = tfdat->when - time(NULL); + if (diff < 0) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() tfnode TRUE no break CALLING >> DIFF=%d <<\n", diff ); + fclose(_F); + /* Already due; call it and rescan. */ tfdat->func(); continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() tfnode TRUE no break NOT calling >> DIFF=%d <<\n", diff ); + fclose(_F); + } if (diff > ZMAXTIMEOUT) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d > %d ZTM_MAX(%d)\n", diff, ZMAXTIMEOUT, ZTM_MAX ); + fclose(_F); + tmoutp->exp100ths = ZMAXTIMEOUT * 100; tmoutp->tp = ZTM_MAX; - } else if (diff > 0) { + } else if (diff >= 0) { exp100ths = diff * 100; if (tmoutp->tp != ZTM_KEY || - exp100ths < tmoutp->exp100ths) { + exp100ths <= tmoutp->exp100ths) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d != %d || %d <= %d ZTM_FUNC(%d)\n", tmoutp->tp, ZTM_KEY, exp100ths, tmoutp->exp100ths, ZTM_FUNC ); + fclose(_F); + tmoutp->exp100ths = exp100ths; tmoutp->tp = ZTM_FUNC; } } break; } /* In case we called a function which messed up the display... */ if (resetneeded) zrefresh(); } @@ -508,20 +548,24 @@ raw_getbyte(long do_keytmout, char *cptr) struct ttyinfo ti; #endif #ifndef HAVE_POLL # ifdef HAVE_SELECT fd_set foofd, errfd; FD_ZERO(&errfd); # endif #endif calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- INIT tmout.tp(%d) ZTM_NONE(%d) ZTM_KEY(%d) / BEGIN RAW_GETBYTE() zle_main.c\n", tmout.tp, ZTM_NONE, ZTM_KEY ); + fclose(_F); /* * Handle timeouts and watched fd's. If a watched fd or a function * timeout triggers we restart any key timeout. This is likely to * be harmless: the combination is extremely rare and a function * is likely to occupy the user for a little while anyway. We used * to make timeouts take precedence, but we can't now that the * timeouts may be external, so we may have both a permanent watched * fd and a long-term timeout. */ @@ -600,43 +644,78 @@ raw_getbyte(long do_keytmout, char *cptr) if (fd > fdmax) fdmax = fd; } } FD_ZERO(&errfd); if (tmout.tp != ZTM_NONE) { expire_tv.tv_sec = tmout.exp100ths / 100; expire_tv.tv_usec = (tmout.exp100ths % 100) * 10000L; tvptr = &expire_tv; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); } - else + else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- FINAL (STOP) tmoutp == ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); + tvptr = NULL; + } winch_unblock(); selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); winch_block(); # endif /* * Make sure a user interrupt gets passed on straight away. */ - if (selret < 0 && (errflag || retflag || breaks || exit_pending)) + if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Doing break [selret:%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + selret, errflag, retflag, breaks, exit_pending ); + fclose(_F); break; + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- NOT doing break selret[%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + selret, errflag, retflag, breaks, exit_pending ); + fclose(_F); + } + /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first * with all fds, then try unsetting the special ones. */ if (selret < 0 && !errtry) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Trying again selret[%d], !errtry[%d] / zle_main.c\n", selret, errtry ); + fclose(_F); + errtry = 1; continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Passed !errtry(errtry:%d) selret[%d] / zle_main.c\n", errtry, selret ); + fclose(_F); + } + if (selret == 0) { /* * Nothing ready and no error, so we timed out. */ switch (tmout.tp) { case ZTM_NONE: /* keeps compiler happy if not debugging */ #ifdef DEBUG dputs("BUG: timeout fired with no timeout set."); #endif @@ -669,20 +748,24 @@ raw_getbyte(long do_keytmout, char *cptr) case ZTM_MAX: /* * Reached the limit of our range, but not the * actual timeout; recalculate the timeout. * We're cheating with the key timeout here: * if one clashed with a function timeout we * reconsider the key timeout from scratch. * The effect of this is microscopic. */ calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "^^^ LOOP-CALLED calc_timeout: tmout.tp == %d / zle_main.c\n", tmout.tp ); + fclose(_F); break; } /* * If we handled the timeout successfully, * carry on. */ if (selret == 0) continue; } /* If error or unhandled timeout, give up. */ @@ -888,22 +971,36 @@ getbyte(long do_keytmout, int *timeout) 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, 0); } icnt = 0; if (errno == EINTR) { die = 0; + static int counter = 0; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Got EINTR %d\n", ++counter ); + fclose(_F); + if (!errflag && !retflag && !breaks && !exit_pending) + { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Continuing despite EINTR / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); continue; + } errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; } else if (errno == EWOULDBLOCK) { fcntl(0, F_SETFL, 0); } else if (errno == EIO && !die) { ret = opts[MONITOR]; opts[MONITOR] = 1; attachtty(mypgrp); @@ -1115,20 +1212,24 @@ zlecore(void) if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Setting error in zlecore.c\n" ); + fclose(_F); errflag |= ERRFLAG_ERROR; break; } redrawhook(); #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ diff --git a/Src/signals.c b/Src/signals.c index e2587dc..0bbda97 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -638,20 +638,25 @@ zhandler(int sig) case SIGINT: if (!handletrap(SIGINT)) { if ((isset(PRIVILEGED) || isset(RESTRICTED)) && isset(INTERACTIVE) && noerrexit < 0) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; errflag |= ERRFLAG_INT; inerrflush(); check_cursh_sig(SIGINT); + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "## set errflag to %d (ERRFLAG_INT:%d) / signals.c\n", errflag, ERRFLAG_INT ); + fclose(_F); } lastval = 128 + SIGINT; } break; #ifdef SIGWINCH case SIGWINCH: adjustwinsize(1); /* check window size and adjust */ (void) handletrap(SIGWINCH); break; ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-10-02 16:26 ` Sebastian Gniazdowski @ 2016-10-02 17:37 ` Sebastian Gniazdowski 0 siblings, 0 replies; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-10-02 17:37 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 1459 bytes --] Investigated this further. The handler isn't exactly late. It is called before errflag checks, but exits here without setting errflag: /* Are we queueing signals now? */ if (queueing_enabled) { The log looks now like this: -- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c ## zhandler(2) signals.c (debug message in first line of zhandler) ## zhandler(2) EXIT 1 signals.c (debug message in if(queueing_enabled)) -- NOT doing break selret[-1/4/4] / zle_main.c: errflag: 0, retflag: 0, breaks: 0, exit_pending: 0 -- Trying again selret[-1], !errtry[0] / zle_main.c -- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c -- (**) NOT doing break selret[0/4/4] / zle_main.c: errflag: 0, retflag: 0, breaks: 0, exit_pending: 0 -- Passed !errtry(errtry:1) selret[0] / zle_main.c ## zhandler(2) signals.c ## set errflag to 2 (ERRFLAG_INT:2) / signals.c -- tmoutp->tp <- ZTM_NONE / calc_timeout( do_keytmout: 0 ), keytimeout: 40 / zle_main.c == CALC_TIMEOUT() one more chance (timedfns exp100ths: 100) -- CALC_TIMEOUT() tfnode TRUE no break NOT calling >> DIFF=1 << -- CALC_TIMEOUT() 0 != 1 || 100 <= 100 ZTM_FUNC(2) ^^^ LOOP-CALLED calc_timeout: tmout.tp == 2 / zle_main.c Interesting is (**) line, it still has errno == 4 (last number in [%d/%d/%d]), apparently errno=0 is needed before select, doing so clears the value. What's with the queueing and early exit from zhandler()? It brings disorder to .recursiveedit. Best regards, Sebastian Gniazdowski [-- Attachment #2: rec5_edit.5.diff.txt --] [-- Type: text/plain, Size: 12304 bytes --] diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a83d41..79d6e20 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -450,47 +450,87 @@ static void calc_timeout(struct ztmout *tmoutp, long do_keytmout) { if (do_keytmout && (keytimeout > 0 || do_keytmout < 0)) { if (do_keytmout < 0) tmoutp->exp100ths = (time_t)-do_keytmout; else if (keytimeout > ZMAXTIMEOUT * 100 /* 24 days for a keypress???? */) tmoutp->exp100ths = ZMAXTIMEOUT * 100; else tmoutp->exp100ths = keytimeout; tmoutp->tp = ZTM_KEY; - } else + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_KEY (%d) / calc_timeout() zle_main.c\n", tmoutp->exp100ths ); + fclose(_F); + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- tmoutp->tp <- ZTM_NONE / calc_timeout( do_keytmout: %d ), keytimeout: %d / zle_main.c\n", do_keytmout, keytimeout ); + fclose(_F); + tmoutp->tp = ZTM_NONE; + } if (timedfns) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "== CALC_TIMEOUT() one more chance (timedfns exp100ths: %d)\n", tmoutp->exp100ths ); + fclose(_F); for (;;) { LinkNode tfnode = firstnode(timedfns); Timedfn tfdat; time_t diff, exp100ths; - if (!tfnode) + if (!tfnode) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() !tfnode break\n" ); + fclose(_F); break; + } tfdat = (Timedfn)getdata(tfnode); diff = tfdat->when - time(NULL); + if (diff < 0) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() tfnode TRUE no break CALLING >> DIFF=%d <<\n", diff ); + fclose(_F); + /* Already due; call it and rescan. */ tfdat->func(); continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() tfnode TRUE no break NOT calling >> DIFF=%d <<\n", diff ); + fclose(_F); + } if (diff > ZMAXTIMEOUT) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d > %d ZTM_MAX(%d)\n", diff, ZMAXTIMEOUT, ZTM_MAX ); + fclose(_F); + tmoutp->exp100ths = ZMAXTIMEOUT * 100; tmoutp->tp = ZTM_MAX; - } else if (diff > 0) { + } else if (diff >= 0) { exp100ths = diff * 100; if (tmoutp->tp != ZTM_KEY || - exp100ths < tmoutp->exp100ths) { + exp100ths <= tmoutp->exp100ths) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- CALC_TIMEOUT() %d != %d || %d <= %d ZTM_FUNC(%d)\n", tmoutp->tp, ZTM_KEY, exp100ths, tmoutp->exp100ths, ZTM_FUNC ); + fclose(_F); + tmoutp->exp100ths = exp100ths; tmoutp->tp = ZTM_FUNC; } } break; } /* In case we called a function which messed up the display... */ if (resetneeded) zrefresh(); } @@ -508,20 +548,24 @@ raw_getbyte(long do_keytmout, char *cptr) struct ttyinfo ti; #endif #ifndef HAVE_POLL # ifdef HAVE_SELECT fd_set foofd, errfd; FD_ZERO(&errfd); # endif #endif calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- INIT tmout.tp(%d) ZTM_NONE(%d) ZTM_KEY(%d) / BEGIN RAW_GETBYTE() zle_main.c\n", tmout.tp, ZTM_NONE, ZTM_KEY ); + fclose(_F); /* * Handle timeouts and watched fd's. If a watched fd or a function * timeout triggers we restart any key timeout. This is likely to * be harmless: the combination is extremely rare and a function * is likely to occupy the user for a little while anyway. We used * to make timeouts take precedence, but we can't now that the * timeouts may be external, so we may have both a permanent watched * fd and a long-term timeout. */ @@ -600,43 +644,78 @@ raw_getbyte(long do_keytmout, char *cptr) if (fd > fdmax) fdmax = fd; } } FD_ZERO(&errfd); if (tmout.tp != ZTM_NONE) { expire_tv.tv_sec = tmout.exp100ths / 100; expire_tv.tv_usec = (tmout.exp100ths % 100) * 10000L; tvptr = &expire_tv; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- tmoutp != ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); } - else + else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "\n-- FINAL (STOP) tmoutp == ZTM_NONE / raw_getbyte() zle_main.c\n" ); + fclose(_F); + tvptr = NULL; + } winch_unblock(); selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); winch_block(); # endif /* * Make sure a user interrupt gets passed on straight away. */ - if (selret < 0 && (errflag || retflag || breaks || exit_pending)) + if (selret < 0 && (errflag || retflag || breaks || exit_pending)) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Doing break [selret:%d/%d/%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + selret, EINTR, errno, errflag, retflag, breaks, exit_pending ); + fclose(_F); break; + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- NOT doing break selret[%d/%d/%d] / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + selret, EINTR, errno, errflag, retflag, breaks, exit_pending ); + fclose(_F); + } + /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first * with all fds, then try unsetting the special ones. */ if (selret < 0 && !errtry) { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Trying again selret[%d], !errtry[%d] / zle_main.c\n", selret, errtry ); + fclose(_F); + errtry = 1; continue; - } + } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Passed !errtry(errtry:%d) selret[%d] / zle_main.c\n", errtry, selret ); + fclose(_F); + } + if (selret == 0) { /* * Nothing ready and no error, so we timed out. */ switch (tmout.tp) { case ZTM_NONE: /* keeps compiler happy if not debugging */ #ifdef DEBUG dputs("BUG: timeout fired with no timeout set."); #endif @@ -669,20 +748,24 @@ raw_getbyte(long do_keytmout, char *cptr) case ZTM_MAX: /* * Reached the limit of our range, but not the * actual timeout; recalculate the timeout. * We're cheating with the key timeout here: * if one clashed with a function timeout we * reconsider the key timeout from scratch. * The effect of this is microscopic. */ calc_timeout(&tmout, do_keytmout); + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "^^^ LOOP-CALLED calc_timeout: tmout.tp == %d / zle_main.c\n", tmout.tp ); + fclose(_F); break; } /* * If we handled the timeout successfully, * carry on. */ if (selret == 0) continue; } /* If error or unhandled timeout, give up. */ @@ -888,22 +971,36 @@ getbyte(long do_keytmout, int *timeout) 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, 0); } icnt = 0; if (errno == EINTR) { die = 0; + static int counter = 0; + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Got EINTR %d\n", ++counter ); + fclose(_F); + if (!errflag && !retflag && !breaks && !exit_pending) + { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Continuing despite EINTR / zle_main.c: errflag: %d, retflag: %d, breaks: %d, exit_pending: %d\n", + errflag, retflag, breaks, exit_pending ); + fclose(_F); continue; + } errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; } else if (errno == EWOULDBLOCK) { fcntl(0, F_SETFL, 0); } else if (errno == EIO && !die) { ret = opts[MONITOR]; opts[MONITOR] = 1; attachtty(mypgrp); @@ -1115,20 +1212,24 @@ zlecore(void) if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "-- Setting error in zlecore.c\n" ); + fclose(_F); errflag |= ERRFLAG_ERROR; break; } redrawhook(); #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ diff --git a/Src/signals.c b/Src/signals.c index e2587dc..ea2f472 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -555,20 +555,23 @@ wait_for_processes(void) unqueue_signals(); } } /* the signal handler */ /**/ mod_export RETSIGTYPE zhandler(int sig) { + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "## zhandler(%d) signals.c\n", sig ); + fclose( _F ); sigset_t newmask, oldmask; #if defined(NO_SIGNAL_BLOCKING) int do_jump; signal_jmp_buf jump_to; #endif last_signal = sig; signal_process(sig); @@ -599,20 +602,24 @@ zhandler(int sig) /* Make sure it's not full (extremely unlikely) */ if (temp_rear != queue_front) { /* ok, not full, so add to queue */ queue_rear = temp_rear; /* save signal caught */ signal_queue[queue_rear] = sig; /* save current signal mask */ signal_mask_queue[queue_rear] = oldmask; } signal_reset(sig); + + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "## zhandler(%d) EXIT 1 signals.c\n", sig ); + fclose( _F ); return; } /* Reset signal mask, signal traps ok now */ signal_setmask(oldmask); switch (sig) { case SIGCHLD: wait_for_processes(); break; @@ -638,20 +645,25 @@ zhandler(int sig) case SIGINT: if (!handletrap(SIGINT)) { if ((isset(PRIVILEGED) || isset(RESTRICTED)) && isset(INTERACTIVE) && noerrexit < 0) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; errflag |= ERRFLAG_INT; inerrflush(); check_cursh_sig(SIGINT); + + // MY DEBUG + FILE *_F = fopen("/tmp/recursive.txt", "a+"); + fprintf( _F, "## set errflag to %d (ERRFLAG_INT:%d) / signals.c\n", errflag, ERRFLAG_INT ); + fclose(_F); } lastval = 128 + SIGINT; } break; #ifdef SIGWINCH case SIGWINCH: adjustwinsize(1); /* check window size and adjust */ (void) handletrap(SIGWINCH); break; ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 20:44 ` Bart Schaefer 2016-10-02 16:26 ` Sebastian Gniazdowski @ 2016-10-05 5:31 ` Sebastian Gniazdowski 2016-10-05 6:14 ` Bart Schaefer 1 sibling, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-10-05 5:31 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 30 September 2016 at 22:44, Bart Schaefer <schaefer@brasslantern.com> wrote: > You may need to find a more aggressive place to reset the timer, such > as in the zle-line-pre-redraw hook, or else create a wrapper widget > for recursive-edit. Was going to do this with periodic hook. Now as 5.3 is fixed I could say: "Share PERIOD with this plugin, set it to value 6...10, best is 10. And if you really want to own PERIOD, then use latest Zsh". However periodic hook rather suffers too from no-timeout select()? Wrapper around recursive-edit would solve Ctrl-C problems, or you meant something about rescheduling? > Either way you'd want to examine $zle_scheduled_events to see if the > timer is still pending, before scheduling it again. Tried accessing the variable from zle widget and no luck. I must be doing something wrong as even ack '.*zle.*sched.*eve.*' doesn't return results. > Or possibly you could switch from doing this with a timer scheduled > function to using a "zle -F" handler function. Cool thing the zle -F, thanks for the tip. It would obviously install where main symptom of problem occurs, at the select(). But how could I periodically change state of the FD, without forking background process for each instance of Zsh? A half-ready solution is to schedule no-op function 24 hours ahead (saw something about that maximum schedule time), this should make calc_timeout() always return ZTM_FUNC. But this requires something more, as the main scheduled function might still stop running because of errflag. Maybe this should be done together with periodic hook. select() would not block (ZTM_FUNC), and periodic hook is maybe immune to errflag rescheduling-break? Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-10-05 5:31 ` Sebastian Gniazdowski @ 2016-10-05 6:14 ` Bart Schaefer 2016-10-05 10:27 ` Sebastian Gniazdowski 0 siblings, 1 reply; 21+ messages in thread From: Bart Schaefer @ 2016-10-05 6:14 UTC (permalink / raw) To: Zsh hackers list On Oct 5, 7:31am, Sebastian Gniazdowski wrote: } Subject: Re: Where to start debugging zle recursive-edit? / Ctrl-C } } On 30 September 2016 at 22:44, Bart Schaefer <schaefer@brasslantern.com> wrote: } > You may need to find a more aggressive place to reset the timer, such } > as in the zle-line-pre-redraw hook, or else create a wrapper widget } > for recursive-edit. } } Was going to do this with periodic hook. For your purposes, the trouble with periodic is that it only executes right before a prompt. Unless there's more to what you're saying than I'm understanding. } However periodic hook rather suffers too from no-timeout select()? I wouldn't expect so, no. It's not related to the select at all. } Wrapper around recursive-edit would solve Ctrl-C problems, or you } meant something about rescheduling? I meant something about scheduling. } > Either way you'd want to examine $zle_scheduled_events } } Tried accessing the variable from zle widget and no luck My typo, it's $zsh_scheduled_events. It's in the documentation for the sched module. } Cool thing the zle -F, thanks for the tip. It would obviously install } where main symptom of problem occurs, at the select(). But how could I } periodically change state of the FD, without forking background } process for each instance of Zsh? Either open a named pipe file (mknod p filename), or use the zsh/tcp module as in the example that appears in the documentation. Another thing I've done quite successfully for a very long time is to assign to the TMOUT variable and use TRAPALRM() to take some action (such as update the time in my prompt). This is close to the same behavior as sched but uses the alarm() system function so doesn't rely on zle read timeouts. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-10-05 6:14 ` Bart Schaefer @ 2016-10-05 10:27 ` Sebastian Gniazdowski 2016-10-05 18:31 ` Bart Schaefer 0 siblings, 1 reply; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-10-05 10:27 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 5 October 2016 at 08:14, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Oct 5, 7:31am, Sebastian Gniazdowski wrote: > } Subject: Re: Where to start debugging zle recursive-edit? / Ctrl-C > } > } On 30 September 2016 at 22:44, Bart Schaefer <schaefer@brasslantern.com> wrote: > } > You may need to find a more aggressive place to reset the timer, such > } > as in the zle-line-pre-redraw hook, or else create a wrapper widget > } > for recursive-edit. > } > } Was going to do this with periodic hook. > > For your purposes, the trouble with periodic is that it only executes > right before a prompt. Unless there's more to what you're saying than > I'm understanding. Had some obstacles to use the precmd but really not recalling them now. > } Wrapper around recursive-edit would solve Ctrl-C problems, or you > } meant something about rescheduling? > > I meant something about scheduling. Hmm, could you reveal? I thought about trapping INT when detected that in .recursive-edit, but directly that's "Ctrl-C problems" stuff > } > Either way you'd want to examine $zle_scheduled_events > } > } Tried accessing the variable from zle widget and no luck > > My typo, it's $zsh_scheduled_events. It's in the documentation for the > sched module. So no need to parse sched output at all, as I once wrote > Either open a named pipe file (mknod p filename), or use the zsh/tcp > module as in the example that appears in the documentation. That are rather heavy-implementation things > Another thing I've done quite successfully for a very long time is to > assign to the TMOUT variable and use TRAPALRM() to take some action > (such as update the time in my prompt). This is close to the same > behavior as sched but uses the alarm() system function so doesn't > rely on zle read timeouts. Thanks for info that this trap doesn't cause problems, I would be definitely anxious about using it (expecting things like e.g. the pick-up of z-sy-h state, but that's maybe plain simple lack of opt localoptions), don't want to serve users heavy-implementation stuff, but if the trap is proven to be robust, then.. Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-10-05 10:27 ` Sebastian Gniazdowski @ 2016-10-05 18:31 ` Bart Schaefer 2016-10-05 20:36 ` Sebastian Gniazdowski 0 siblings, 1 reply; 21+ messages in thread From: Bart Schaefer @ 2016-10-05 18:31 UTC (permalink / raw) To: Zsh hackers list On Oct 5, 12:27pm, Sebastian Gniazdowski wrote: } } > } Wrapper around recursive-edit would solve Ctrl-C problems, or you } > } meant something about rescheduling? } > } > I meant something about scheduling. } } Hmm, could you reveal? This was proposed before we'd identified the problem with the signal queue getting too deep, so may not be helpful any more; but the idea is that since ^C returns you to the caller of recursive-edit, this means precmd is not run. So if you need to reset something that is normally handled in precmd, you should include that part of precmd in the wrapper, calling it after "zle .recursive-edit" returns. } I thought about trapping INT when detected that } in .recursive-edit, but directly that's "Ctrl-C problems" stuff trap 'zle && zle .send-break' INT # might be helpful with localtraps } > Either open a named pipe file (mknod p filename), or use the zsh/tcp } > module as in the example that appears in the documentation. } } That are rather heavy-implementation things Is having a named pipe file really that much heavier than having the shared text file plus that external flocking app to synchronize the access to it? ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-10-05 18:31 ` Bart Schaefer @ 2016-10-05 20:36 ` Sebastian Gniazdowski 0 siblings, 0 replies; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-10-05 20:36 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 5 October 2016 at 20:31, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Oct 5, 12:27pm, Sebastian Gniazdowski wrote: > } I thought about trapping INT when detected that > } in .recursive-edit, but directly that's "Ctrl-C problems" stuff > > trap 'zle && zle .send-break' INT # might be helpful with localtraps Thanks, was about to search for a way to interrupt recursive-edit. > } > Either open a named pipe file (mknod p filename), or use the zsh/tcp > } > module as in the example that appears in the documentation. > } > } That are rather heavy-implementation things > > Is having a named pipe file really that much heavier than having the > shared text file plus that external flocking app to synchronize the > access to it? Binaries are cool if they are created using small, portable C code. Compilation is fast, without "strcasestr() exists?" problems, and so many such C programs out there, expecting them to compile everywhere after I compiled util-linux/flock on FreeBSD and OS X. Tried to convert program "highlight" to return region_highlight and it was much worse because it's large C++ code without configure script. Thinking about what's actually heavy and what's not made me realize that I might refuse a good solution, after all it's only one *period_passed function that needs to be called. Will check this soon. Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 11:28 ` Sebastian Gniazdowski 2016-09-30 13:30 ` Sebastian Gniazdowski @ 2016-09-30 21:45 ` Bart Schaefer 2016-09-30 21:54 ` Sebastian Gniazdowski 1 sibling, 1 reply; 21+ messages in thread From: Bart Schaefer @ 2016-09-30 21:45 UTC (permalink / raw) To: Zsh hackers list On Sep 30, 1:28pm, Sebastian Gniazdowski wrote: } } The stack trace is at the end. Is this a trace from a place where you sometimes get a core dump or unexpected exit? Because I don't see indication in the stack trace that menu selection is active, for example. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Where to start debugging zle recursive-edit? / Ctrl-C 2016-09-30 21:45 ` Bart Schaefer @ 2016-09-30 21:54 ` Sebastian Gniazdowski 0 siblings, 0 replies; 21+ messages in thread From: Sebastian Gniazdowski @ 2016-09-30 21:54 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh hackers list On 30 September 2016 at 23:45, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Sep 30, 1:28pm, Sebastian Gniazdowski wrote: > } > } The stack trace is at the end. > > Is this a trace from a place where you sometimes get a core dump or > unexpected exit? Because I don't see indication in the stack trace > that menu selection is active, for example. No, no luck with the crashes. It's a stack trace after Ctrl-C when in .recursiveedit, i.e. when the Ctrl-R widget was invoked. The stressors were commented out in zshrc. BTW. I was running multiple jobs because on IRC one user said that he gets crashes when multiple jobs in background. Didn't ask of ZSH_VERSION. Tomorrow will try with Zconvey disabled, the Ctrl-C problems appeared after additional complex-char mappings (e.g. cursors) so there should be something to examine. Best regards, Sebastian Gniazdowski ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2016-10-06 0:46 UTC | newest] Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-09-23 16:26 Where to start debugging zle recursive-edit? / Ctrl-C Sebastian Gniazdowski 2016-09-24 20:31 ` Bart Schaefer 2016-09-24 20:58 ` Sebastian Gniazdowski 2016-09-25 7:09 ` Daniel Shahaf 2016-09-26 22:16 ` Sebastian Gniazdowski 2016-09-27 16:09 ` Bart Schaefer 2016-09-29 9:30 ` Sebastian Gniazdowski 2016-09-29 17:07 ` Bart Schaefer 2016-09-30 9:04 ` Sebastian Gniazdowski 2016-09-30 11:28 ` Sebastian Gniazdowski 2016-09-30 13:30 ` Sebastian Gniazdowski 2016-09-30 20:44 ` Bart Schaefer 2016-10-02 16:26 ` Sebastian Gniazdowski 2016-10-02 17:37 ` Sebastian Gniazdowski 2016-10-05 5:31 ` Sebastian Gniazdowski 2016-10-05 6:14 ` Bart Schaefer 2016-10-05 10:27 ` Sebastian Gniazdowski 2016-10-05 18:31 ` Bart Schaefer 2016-10-05 20:36 ` Sebastian Gniazdowski 2016-09-30 21:45 ` Bart Schaefer 2016-09-30 21:54 ` Sebastian Gniazdowski
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).