On 3 October 2016 at 01:21, Bart Schaefer wrote: > There seem to be a bunch of inter-related things going on here. > > The first is that recursiveedit() calls zlecore() which calls > getkeycmd() which cascades into raw_getbyte() with do_keytmout = 0 > which in some circumstances means that raw_getbyte() effectively > does a blocking read on its first call and only runs the sched > after a key is pressed. I haven't figured out what's wrong with > the calc_timeout() logic that makes this possible, but it's a > race -- it happens only once in a while. It could be either way, if this is to be resolved. I mean, stopping sched when in .recursive-edit has some, if not total sense. It's like if user would be in an application. > The second is that zlecore() expects to be entered with the signal > queue disabled, but zle widgets are called with queueing enabled, so > recursiveedit() needs save/zero/restore the queue level around the > call to zlecore(). > > The third is that somewhere below execstring() from checksched(), > the signal queueing level is being incremented but not decremented. > The problem is that the execution code calls itself recursively so > deeply that I can't pinpoint the place this occurs. Even with a > watchpoint on queueing_enabled, it looks as though we should be > fine -- it's as if the recursive calls never quite unwind all the > way back to the top, but printing stack traces in gdb doesn't show > that happening at any place where queueing_enabled changes. > > Usually the third effect is hidden by the restore_queue_signals() > in getbyte(), but when in recursiveedit() the queue_signal_level() > in raw_getbyte() starts out > 0, and never goes all the way back > down again. Or something like that. I expected fixing the second > problem to again mask the third, but it does not. > > It's almost like there's a tail-call optimization occuring that is > causing an unqueue_signals() to be skipped. And in fact there are > cases where the queueing_enabled is decremented but the watchpoint > mysteriously does not trigger -- I see the smaller "old" value the > next time the watchpoint triggers on the *increment*, but I never > see the assignment that reduces the value. I think this is because > gdb actually stops on the NEXT instruction AFTER the watched location, > and there are some places where there is no breakable next line (the > unqueue_signals() is the last line of a function). > > It's quite normal for queueing_enabled to run up to 12 or so on a > normal execution stack and still decrement all the way back to zero, > so watching for a high-water mark is nearly useless. Early this morning I read this text like if watchpoints didn't work and now did whole path from recursiveedit to second raw_getbyte() call. In lldb watchpoitns worked apparently always correctly, maybe because I have no optimizations. Forgot to set breakpoint on raw_getbyte() and ended in going multiple steps "repeated", but maybe that's a luck, because vim/:setscrollbind shows nicely where repetition starts and that queueing_enabled is off by 1: https://asciinema.org/a/2c4p285gujuv0850uinrmj2le The first common entry is #8. I submit and now start to think about what's gathered. Best regards, Sebastian Gniazdowski