From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13214 invoked by alias); 6 Dec 2014 00:36:07 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 33878 Received: (qmail 16056 invoked from network); 6 Dec 2014 00:36:05 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=mv2V5d2TGXNjtemE1X1B99Ial+VPQAjz70DF9jQifFg=; b=nLIh/QXMbQok4HFO5bUitaky8bE6KYWjiPDp95kuX+aiuyziBTl7oPbOfvLf8bNWEn 9a7A3LpzjGWrJZYA/S444b8+15GLaf7lbUP3TQoIG/bNoEktRYaCkEPoSM142FUbHvvu WPheLIIviFZyOaZE5xwgR+CkVh9XIC9BX4OHDM8ZiGkwzDKb/Gq0heHAYSZ1Lg/mElXJ /RkAJBiSfNQ2XHhSe/KPNMUELr47hmqA2Nu78yBHA5hFlETBk7A4mPULtF2heAndAbn2 vxmq9Huurkb3pLsbAs4t1BOu5iGaGkrtCpo1lEg5Qa1sMoLb0X610kgrvUVe/tRP5j/p SNpA== MIME-Version: 1.0 X-Received: by 10.107.128.87 with SMTP id b84mr1357095iod.42.1417826162981; Fri, 05 Dec 2014 16:36:02 -0800 (PST) In-Reply-To: <20141205220717.2f86bdd2@pws-pc.ntlworld.com> References: <20141202155452.647182b4@pwslap01u.europe.root.pri> <141202084858.ZM31517@torch.brasslantern.com> <20141202172654.30e7d380@pwslap01u.europe.root.pri> <141204085606.ZM9146@torch.brasslantern.com> <20141204171226.301e9d2c@pwslap01u.europe.root.pri> <141205002023.ZM19736@torch.brasslantern.com> <20141205145054.655a2f70@pwslap01u.europe.root.pri> <141205100632.ZM508@torch.brasslantern.com> <20141205181330.2b458b46@pwslap01u.europe.root.pri> <20141205203417.2bc66b7b@pws-pc.ntlworld.com> <20141205220717.2f86bdd2@pws-pc.ntlworld.com> Date: Sat, 6 Dec 2014 01:36:02 +0100 Message-ID: Subject: Re: Interrupting globs (Re: Something rotten in tar completion) From: Mikael Magnusson To: Peter Stephenson Cc: "Zsh Hackers' List" Content-Type: text/plain; charset=UTF-8 On Fri, Dec 5, 2014 at 11:07 PM, Peter Stephenson wrote: > On Fri, 5 Dec 2014 20:34:17 +0000 > Peter Stephenson wrote: >> On the other problem I came up with, that eval is resetting errflag even >> if you've interrupted: how about the following? Add a bit to errflag to >> signify that the user interrupted the shell rather than that some >> internal error (e.g. syntax) occurred. Only reset this new bit in a few >> key places: the main command loop when executing, the top of ZLE when >> editing being the obvious places. Convert other "errflag = 0" >> assignments case by case so that they just remove bit 0; then eval can >> continue to do its job of acting as a sandbox but without screwing up >> the behaviour of interrupts. I think doing that is fairly mechanical >> and it achieves what's needed without compromising anything else. > > Here's my first go; it does seem to do what I want, and as a by-product > fixes all the little race conditions we've always had that meant you > couldn't interrupt chunks of code that were executed in any kind of > sandbox because the condition got reset afterwards. I think a few of > these have been annoying me over the years. > > The general strategy is to use the bit ERRFLAG_ERROR for internal > failures and ERRFLAG_INT for user interrupts. There are only two > cases of the latter: on an untrapped SIGINT, the obvious case, and also > on a trapped SIGINT or SIGQUIT where we've been told to behave as if the > trap didn't trap the error condition. That's straightforward for > SIGINT, less so for SIGQUIT but I took my cue from the fact that Bart > thought it worthwhile trapping SIGQUIT as an interactive "no, I really > mean abort" in completion, which implies that if we trap it we want it > to work at least as well as SIGINT. > > Correspondingly, most of the time only the ERRFLAG_ERROR bit gets > reset. ERRFLAG_INT gets reset only in the following cases: > > - in the main command loop. This is what causes the shell not to exit but > instead go back to the main command loop when you ^C a command. > > - at the start of zleread, so we can read the next thing to do whatever > just happened. I'm not sure this is particularly useful since > in this case you'd typically expect the previous condition to have > occurred and it could mean e.g. you ignore an interrupt that > occurred just before a "vared". > > - when we just finished completion. This is needed so that the cases > that got this whole business kicked off behave as now (but more > reliably) --- a ^C gets you back to the command line, but the command > line is not trashed as it would be if you ^Ced outside completion (try > it if you're confused). There's a race here, but it's no worse than it > ever was. > > To ensure ERRFLAG_INT doesn't get reset unnecessarily there are a number > of cases where restoring errflag to a previously saved value keeps the > ERRFLAG_INT bit if it got set in the meanwhile. I hope the rationale > here is obvious --- the ERRFLAG_ERROR is an internal state that needs > resetting, the ERRFLAG_INT an asynchronous condition where the user > doesn't care what the internal state is. > > By the way, looking at the patch below you might wonder if it wouldn't > be more efficient to add a separate flag for interrupt error conditions > to test. It wouldn't --- there are many more cases where errflag is > tested than when it is set, not affected by the patch below. > > I suspect we'll just have to try this out and see how it works. This seems to work well for me in the cases you talked about, but I quickly noticed one surprising problem. I have some stuff in my chpwd() hook to show git branches and stuff, and these used to be interruptible by ctrl-c (the commands are very fast with hot cache, but can be somewhat painful with cold cache, like 5-10 seconds delay). With the patch, I cannot interrupt them (sometimes?). chpwd () { stty -echo >&/dev/null test -f .tdldb && tdll -1 >&2 test -d .git && { git branch test -d .git/svn && { echo -n r git svn find-rev master } git name-rev HEAD git describe --tags HEAD 2> /dev/null } >&2 if [[ "$_NONOCDLS" = 1 ]] then ls $LS_OPTIONS >&2 fi } The git branch is actually git brunch, which is git aliased to brunch -- alias for '!git branch -v|sed -e 's/t/ /g' -e 's/(.{'$(( $(tput cols) - 1 ))'}) There's no .tdldb in that directory either, but including it unmodified anyway. -- Mikael Magnusson