On 30 September 2016 at 22:44, Bart Schaefer 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