From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9629 invoked by alias); 20 Mar 2016 02:07:41 -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: 38188 Received: (qmail 11415 invoked from network); 20 Mar 2016 02:07:37 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_DKIM_INVALID autolearn=ham autolearn_force=no version=3.4.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brasslantern-com.20150623.gappssmtp.com; s=20150623; h=from:message-id:date:in-reply-to:comments:references:to:subject :mime-version; bh=2hZ8gwLnuGVaGmA96tjQe8eP4SYww0Jxgd/r0hQn8l4=; b=jWM4m99AMzt5o1QoULzDrD9BcDV3D0K5ESfOamaGlZExIxD3AmIMTucJxY6MZbBhAT DrSF0LwbRW/7N+v9BLqNQqZffGWjQ5q5/4X7RLrxNcRjtlXn5sQ2gMosO5hpZRzZWFtw NJtm7Lpq847UYhcFKYJwmNJS9Mph9oQKDmZZPndqC8eLNmpkDC6VAqx3Nl38itydVJGH uKEUavv+x2cFl7s1siHJ8Wh0ItJIaUQuTb3JXsbZBcW/wCvMyQY+QQiIno/PyCaxRTho 6Q1VRle5Xm/hXbelZoqJkdURqW/RnSFVJ+cwtOt9b1uWMgZrRWRjgDdP7DJj1JsbcWQl r9cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:message-id:date:in-reply-to:comments :references:to:subject:mime-version; bh=2hZ8gwLnuGVaGmA96tjQe8eP4SYww0Jxgd/r0hQn8l4=; b=b63TEzwPdfrykpeBp6vwuu6zbHH9ecfUt9E0ytYtpsV9iNQDpScs89gp1iA/KxwMS7 G7+n6P0a9Bh0x0YVvawbATwNPBHFVVByKyFAOCs68bkOslnvlsDDMAvEZ606YRWFBgDh V1MCYJVcYGbpapZoJTEmu7e+WNI31xB4p8Ukhli0DNCXyavLMLu6nBRrzwnygsIWOa2X hc2FsyMEWBy8jJnp3PFS0wZMkIqjL9vmQu5NhRvqYObAo2iAsBiX7WnzehD+bDDH7RwM P2qnRc2DfN4doVefVvp0L5lXhVVe27vv+1udrcJJg2EYBr9Jjjl1Nf6XjDzL/HlUkrCr y/aA== X-Gm-Message-State: AD7BkJIq7k3bO+IB460uTUGmFcccOkjRzCsmTI5QP4xlzM4sgn/2b818FUpBc7RhCU0LoA== X-Received: by 10.66.55.39 with SMTP id o7mr34404344pap.13.1458439650219; Sat, 19 Mar 2016 19:07:30 -0700 (PDT) From: Bart Schaefer Message-Id: <160319190757.ZM28874@torch.brasslantern.com> Date: Sat, 19 Mar 2016 19:07:57 -0700 In-Reply-To: <160317111515.ZM16697@torch.brasslantern.com> Comments: In reply to Bart Schaefer "Re: segfault in completion for configure" (Mar 17, 11:15am) References: <20160311134729.GA32476@cventin.lip.ens-lyon.fr> <20160311143202.4008e29b@pwslap01u.europe.root.pri> <160311150056.ZM30997@torch.brasslantern.com> <20160312031116.GC28459@zira.vinc17.org> <160312082029.ZM2340@torch.brasslantern.com> <160312093420.ZM14020@torch.brasslantern.com> <20160313215831.GA23404@zira.vinc17.org> <160314194323.ZM6887@torch.brasslantern.com> <20160317152435.GC11303@cventin.lip.ens-lyon.fr> <160317111515.ZM16697@torch.brasslantern.com> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: segfault in completion for configure MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii On Mar 17, 11:15am, Bart Schaefer wrote: } } Yeah, nothing really new here, this is exactly what I would expect } to see: The hander returns and thereafter pattern matching is messed } up and crashes when it tries to pick up where it left off. Well, I think I've isolated this, but I don't know what to do about it. The set of globals that are getting messed up are these: /* * Run a pattern. */ static char *patinstart; /* Start of input string */ static char *patinend; /* End of input string */ static char *patinput; /* String input pointer */ static char *patinpath; /* Full path for use with ~ exclusions */ static int patinlen; /* Length of last successful match. * Includes count of Meta characters. */ static char *patbeginp[NSUBEXP]; /* Pointer to backref beginnings */ static char *patendp[NSUBEXP]; /* Pointer to backref ends */ static int parsfound; /* parentheses (with backrefs) found */ This set is all referenced from pattryrefs() and other functions that it calls. The problem is that they also describe the state of backrefs, so it's difficult to save/restore them such that $match et al. remain sane across a signal handler (and when not sane, they point off into unknown territory and crashing ensues). The problem is that it's exactly during the time that these globals are volatile that we want to allow signal handling, so that a deep recursive glob or pathological pattern match can be interrupted [see patmatch(), "while (scan && !errflag)"]. The patch below crams all those globals into a struct so they can be saved/restored as one, and then tries pushing the signal queue management down into patmatch() from pattryrefs(). A side-effect of this patch is that the following is no longer guaranteed to work: typeset -i trap_handled; TRAPUSR2() { setopt localoptions extendedglob [[ $somestring = (#b)$~somepattern ]] trap_handled=1 } TRAPUSR1() { [[ $TERM = screen ]] && print $something } while true; do if ((trap_handled)); then trap_handled=0 print $match[0] # This may not be the backref from TRAPUSR2 fi done Specifically, if the signals arrive in order USR1 USR2 such that USR2 is handled during the [[ ]] expression in TRAPUSR1, then the state from TRAPUSR2 will be discarded. I don't know if/how we ought to document. Of course if this DOESN'T solve Vincent's crash, then all of the above is moot because I've mis-diagnosed again. diff --git a/Src/pattern.c b/Src/pattern.c index 72c7d97..4e2f236 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -1838,7 +1838,8 @@ pattail(long p, long val) /* do pattail, but on operand of first argument; nop if operandless */ /**/ -static void patoptail(long p, long val) +static void +patoptail(long p, long val) { Upat ptr = (Upat)patout + p; int op = P_OP(ptr); @@ -1854,19 +1855,34 @@ static void patoptail(long p, long val) /* * Run a pattern. */ -static char *patinstart; /* Start of input string */ -static char *patinend; /* End of input string */ -static char *patinput; /* String input pointer */ -static char *patinpath; /* Full path for use with ~ exclusions */ -static int patinlen; /* Length of last successful match. +struct rpat { + char *patinstart; /* Start of input string */ + char *patinend; /* End of input string */ + char *patinput; /* String input pointer */ + char *patinpath; /* Full path for use with ~ exclusions */ + int patinlen; /* Length of last successful match. * Includes count of Meta characters. */ -static char *patbeginp[NSUBEXP]; /* Pointer to backref beginnings */ -static char *patendp[NSUBEXP]; /* Pointer to backref ends */ -static int parsfound; /* parentheses (with backrefs) found */ + char *patbeginp[NSUBEXP]; /* Pointer to backref beginnings */ + char *patendp[NSUBEXP]; /* Pointer to backref ends */ + int parsfound; /* parentheses (with backrefs) found */ + + int globdots; /* Glob initial dots? */ +}; + +static struct rpat pattrystate; + +#define patinstart (pattrystate.patinstart) +#define patinend (pattrystate.patinend) +#define patinput (pattrystate.patinput) +#define patinpath (pattrystate.patinpath) +#define patinlen (pattrystate.patinlen) +#define patbeginp (pattrystate.patbeginp) +#define patendp (pattrystate.patendp) +#define parsfound (pattrystate.parsfound) +#define globdots (pattrystate.globdots) -static int globdots; /* Glob initial dots? */ /* * Character functions operating on unmetafied strings. @@ -2302,7 +2318,7 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, * Either we are testing against a pure string, * or we can match anything at all. */ - int ret, pstrlen; + int pstrlen; char *pstr; if (patstralloc->alloced) { @@ -2404,11 +2420,7 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, } } } - - return ret; } else { - int q = queue_signal_level(); - /* * Test for a `must match' string, unless we're scanning for a match * in which case we don't need to do this each time. @@ -2440,9 +2452,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, ret = 0; } } - if (!ret) { + if (!ret) return 0; - } patglobflags = prog->globflags; if (!(patflags & PAT_FILE)) { @@ -2454,8 +2465,6 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, patinput = patinstart; - dont_queue_signals(); - if (patmatch((Upat)progstr)) { /* * we were lazy and didn't save the globflags if an exclusion @@ -2594,11 +2603,9 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, ret = 1; } else ret = 0; - - restore_queue_signals(q); - - return ret; } + + return ret; } /* @@ -2674,6 +2681,26 @@ patmatch(Upat prog) int savglobflags, op, no, min, fail = 0, saverrsfound; zrange_t from, to, comp; patint_t nextch; + int q = queue_signal_level(); + + /* + * To avoid overhead of saving state if there are no queued signals + * waiting, we pierce the signals.h veil and examine queue state. + */ +#define check_for_signals() do if (queue_front != queue_rear) { \ + int savpatflags = patflags, savpatglobflags = patglobflags; \ + char *savexactpos = exactpos, *savexactend = exactend; \ + struct rpat savpattrystate = pattrystate; \ + dont_queue_signals(); \ + restore_queue_signals(q); \ + exactpos = savexactpos; \ + exactend = savexactend; \ + patflags = savpatflags; \ + patglobflags = savpatglobflags; \ + pattrystate = savpattrystate; \ + } while (0) + + check_for_signals(); while (scan && !errflag) { next = PATNEXT(scan); @@ -3508,6 +3535,9 @@ patmatch(Upat prog) } scan = next; + + /* Allow handlers to run once per loop */ + check_for_signals(); } return 0;