From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Robert Weiner Newsgroups: gmane.emacs.bugs Subject: bug#61436: Emacs Freezing With Java Files Date: Thu, 18 Apr 2024 22:58:15 -0400 Message-ID: References: <835yc6hl0c.fsf@gnu.org> <87bkd7fsp4.fsf@sappc2.fritz.box> <87il7ew5wx.fsf@sappc2.fritz.box> <87il7dbosk.fsf@lidells.se> <87r0m1t0el.fsf@sappc2.fritz.box> <875y3bbokx.fsf@sappc2.fritz.box> Reply-To: rswgnu@gmail.com Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="000000000000e4de1506166a4396" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="5304"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Hank Greenburg , Jens Schmidt , Eli Zaretskii , Mats Lidell , 61436@debbugs.gnu.org To: Alan Mackenzie Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Fri Apr 19 05:00:11 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rxeTy-0001BY-Er for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 19 Apr 2024 05:00:10 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxeTe-0008UO-FF; Thu, 18 Apr 2024 22:59:50 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxeTc-0008UD-RF for bug-gnu-emacs@gnu.org; Thu, 18 Apr 2024 22:59:48 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rxeTc-0004yG-Jb for bug-gnu-emacs@gnu.org; Thu, 18 Apr 2024 22:59:48 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rxeTq-0007CC-1h for bug-gnu-emacs@gnu.org; Thu, 18 Apr 2024 23:00:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Robert Weiner Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 19 Apr 2024 03:00:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 61436 X-GNU-PR-Package: emacs Original-Received: via spool by 61436-submit@debbugs.gnu.org id=B61436.171349554527196 (code B ref 61436); Fri, 19 Apr 2024 03:00:02 +0000 Original-Received: (at 61436) by debbugs.gnu.org; 19 Apr 2024 02:59:05 +0000 Original-Received: from localhost ([127.0.0.1]:56146 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rxeSu-00074a-F6 for submit@debbugs.gnu.org; Thu, 18 Apr 2024 22:59:05 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:55866) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rxeSs-00074D-It for 61436@debbugs.gnu.org; Thu, 18 Apr 2024 22:59:03 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxeSZ-0004sB-Bl for 61436@debbugs.gnu.org; Thu, 18 Apr 2024 22:58:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=To:Subject:Date:From:In-Reply-To:References: MIME-Version; bh=C18bFuypEzAjSaLtiZCX1sYTJ2qQGIsokwYcNAOfHdM=; b=SAATtZSJ6YYu sliy3tNBrH70hwfIVRNSdpe4S8HgHypJoUOAcy82+afZR7NFyvYW07/uCBRs3A6LE5y0vTC49VIcl SHliHI0yXpozFoa720ang4WQN0UwB7tQAEGudr76lVLT3Kq2VQc7xlFZ+IjW+yqia5ieha4wWICbB sxOCj/ZBj/TiXLgQWqJz9iYMC5hN8DI4OOdYO7DY+QfOi20r9K7LfUdCr7M+Skk83nEKFQrhBGuFm YtTVjH89icH3irVYJQgOR110iFZhBye5l+Kc5ghUsKpGdM00cJzrf6NNuLkoGHn4VN7fNF8B8frK2 r2JcYGRuXQz3u2tQmrSCPA==; X-Forwarded-Encrypted: i=1; AJvYcCVEik+rdUOKH+Xqnil6qI+N2JjjRKWLjHpWz2ojHIQlgjuxJpD17yXj9Iht0mKhCXeNCOaDiwQTiOZ3raqSocbUwxaL0CE= X-Gm-Message-State: AOJu0Ywex2gKQ6+hpDsZQeLRv8m8TakTJjv3OMcKDEV5k84w5ZXgwQyL NGAQfqQ7YJNASJvfLGGWZYnWPWAY3IxqLH6HeeFTLMmGRN0MEtAYqFkXAFdgYkLZXcuYmQDuHLF 69FAw3A2or6hFyYdLwrhZ6yb4EII= X-Google-Smtp-Source: AGHT+IE4sMp6ib2leBrF2/qVPYPOl4uqvvEQ8CVAKQPOTqgTe01Pggd8CX9+j2ZljvzZUJPvTNf47G2RVjQH3pmingg= X-Received: by 2002:a05:6102:2929:b0:47a:d9f5:4154 with SMTP id cz41-20020a056102292900b0047ad9f54154mr768160vsb.1.1713495521675; Thu, 18 Apr 2024 19:58:41 -0700 (PDT) In-Reply-To: X-Gmail-Original-Message-ID: X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:283626 Archived-At: --000000000000e4de1506166a4396 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Alan: This is to confirm that I have tested your cc-defs.el patch works properly and eliminates the Emacs hang when using the Hyperbole java-defun-prompt-regexp. Nice work. Regards, Bob On Fri, Oct 13, 2023 at 8:42=E2=80=AFAM Alan Mackenzie wrote: > Hello, Jens. > > On Thu, Oct 12, 2023 at 21:58:06 +0200, Jens Schmidt wrote: > > Hi Alan, > > > Alan Mackenzie writes: > > [ .... ] > > > >> That always freezes Emacs (29 and master) even before it has a chanc= e > to > > >> display P1.java. The freeze happens in function > > >> `c-get-fallback-scan-pos', where the while loop inf-loops. > > Yes. > > > > c-get-fallback-scan-pos tries to move to the beginning of a function. > > > This probably involves defun-prompt-regexp when it is non-nil. :-( > > > Otherwise we would see hangs or exponential behavior (?) somewhere in > > the Emacs regexp machinerie, but they take place in that while loop. S= o > > I guess that there must be some other, additional quality that this > > regexp fulfills. Like: "matches the empty string" (which it does not, > > as far as I can tell) or: "must only match before curlies" or whatnot. > > > Unfortunately, the doc string/info doc of `defun-prompt-regexp=C2=B4 pr= ovides > > only exactly that latter criterion: > > > That is to say, a defun begins on a line that starts with a match for > > this regular expression, followed by a character with open-parenthesi= s > > syntax. > > > I guess that only pruning that regexp until things start unfreezing > > could give an answer here. Or more tracing to see how point moves in > > `c-get-fallback-scan-pos'. But I need some tracing break here ... > > > > ... or so I thought, I just couldn't resist: > > > I expanded and instrumented that function from emacs-29 as follows, > > (hopefully) not changing any of its logic: > > > ------------------------- snip ------------------------- > > (defun c-get-fallback-scan-pos (here) > > ;; Return a start position for building `c-state-cache' from scratch. > This > > ;; will be at the top level, 2 defuns back. Return nil if we don't > find > > ;; these defun starts a reasonable way back. > > (message "c-get-fallback-scan-pos") > > (save-excursion > > (save-restriction > > (when (> here (* 10 c-state-cache-too-far)) > > (narrow-to-region (- here (* 10 c-state-cache-too-far)) here)) > > ;; Go back 2 bods, but ignore any bogus positions returned by > > ;; beginning-of-defun (i.e. open paren in column zero). > > (goto-char here) > > (let ((cnt 2)) > > (message "beginning-of-defun-loop-00: %d %d" cnt (point)) > > (while (not (or (bobp) (zerop cnt))) > > (message "beginning-of-defun-loop-01: %d" (point)) > > (let (beginning-of-defun-function end-of-defun-function) > > (beginning-of-defun)) > > (and defun-prompt-regexp > > (looking-at defun-prompt-regexp) > > (message "beginning-of-defun-loop-02: %d" (point)) > > (goto-char (match-end 0))) > > (message "beginning-of-defun-loop-03: %d" (point)) > > (if (eq (char-after) ?\{) > > (setq cnt (1- cnt))))) > > (and (not (bobp)) > > (point))))) > > ------------------------- snip ------------------------- > > > That results in the message triple > > > ------------------------- snip ------------------------- > > beginning-of-defun-loop-01: 5879 > > beginning-of-defun-loop-02: 5801 > > beginning-of-defun-loop-03: 5879 > > beginning-of-defun-loop-01: 5879 > > beginning-of-defun-loop-02: 5801 > > beginning-of-defun-loop-03: 5879 > > ... > > ------------------------- snip ------------------------- > > > inf-looping. These points are (|: 5801, ^: 5879) here in P1.java: > > > ------------------------- snip ------------------------- > > 178 } catch (Exception e) { > > 179| error("symTable.addDecl", "unexpected error with a single > HashMap " + e)^; > > 180 } > > 181 > > ------------------------- snip ------------------------- > > > So the catch-block just before line 181 is recognized as a potential BO= D > > (previous trailing open curly?). But then `defun-prompt-regexp' matche= s > > the function call in the catch-block as defun prompt regexp (which it > > better should not?), taking point back to where, on next BOD search, th= e > > exact previous BOD is found again. > > > So probably there are really two issues here: > > > 1. The `defun-prompt-regexp' used by Hyperbole, which matches too > > broadly, and > > > 2. function `c-get-fallback-scan-pos', which could try harder to avoid > > inf-loops when such things happen. > > > But that's where I *really* stop here :-) > > You've diagnosed the bug completely. Thanks! The hang was caused > entirely by the loop in c-get-fallback-scan-pos, not the deficiencies in > that long regexp. > > defun-prompt-regexp, when appended with a \\s( (as is done in > beginning-of-defun-raw) matches the " error(" on L179 of P1.java. > The bare defun-prompt-regexp (as used in CC Mode) matches the entire > line except the terminating ;. This regexp could do with some > amendment, but it is not the main cause of the bug. > > To solve the bug, I'm amending the macro c-beginning-of-defun-1 so that > it only stops at a debug-prompt-regexp position when it also found a {. > Otherwise it will keep looping until it finds a better position or BOB. > > Would all concerned please apply the attached patch to the Emacs master > branch, directory lisp/progmodes. Then please byte compile CC Mode in > full (a macro has been changed), and try the result on your real Java > code. (If anybody wants any help applying the patch or byte compiling, > feel free to send me private mail.) Then please confirm that the bug is > indeed fixed. Thanks! > > -- > Alan Mackenzie (Nuremberg, Germany). > > --000000000000e4de1506166a4396 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Alan:

This is to confirm that I have tested your cc-= defs.el patch works properly and eliminates the Emacs hang when using the H= yperbole java-defun-prompt-regexp.=C2=A0 Nice work.

Regards,
=

=
Bob


On Fri, Oct 13, 2023 at 8:42=E2=80=AFAM Alan Mackenzie <= ;acm@muc.de> wrote:
Hello, Jens.

On Thu, Oct 12, 2023 at 21:58:06 +0200, Jens Schmidt wrote:
> Hi Alan,

> Alan Mackenzie <acm= @muc.de> writes:

[ .... ]

> >> That always freezes Emacs (29 and master) even before it has = a chance to
> >> display P1.java.=C2=A0 The freeze happens in function
> >> `c-get-fallback-scan-pos', where the while loop inf-loops= .

Yes.

> > c-get-fallback-scan-pos tries to move to the beginning of a funct= ion.
> > This probably involves defun-prompt-regexp when it is non-nil.=C2= =A0 :-(

> Otherwise we would see hangs or exponential behavior (?) somewhere in<= br> > the Emacs regexp machinerie, but they take place in that while loop.= =C2=A0 So
> I guess that there must be some other, additional quality that this > regexp fulfills.=C2=A0 Like: "matches the empty string" (whi= ch it does not,
> as far as I can tell) or: "must only match before curlies" o= r whatnot.

> Unfortunately, the doc string/info doc of `defun-prompt-regexp=C2=B4 p= rovides
> only exactly that latter criterion:

>=C2=A0 =C2=A0That is to say, a defun begins on a line that starts with = a match for
>=C2=A0 =C2=A0this regular expression, followed by a character with open= -parenthesis
>=C2=A0 =C2=A0syntax.

> I guess that only pruning that regexp until things start unfreezing > could give an answer here.=C2=A0 Or more tracing to see how point move= s in
> `c-get-fallback-scan-pos'.=C2=A0 But I need some tracing break her= e ...


> ... or so I thought, I just couldn't resist:

> I expanded and instrumented that function from emacs-29 as follows, > (hopefully) not changing any of its logic:

> ------------------------- snip -------------------------
> (defun c-get-fallback-scan-pos (here)
>=C2=A0 =C2=A0;; Return a start position for building `c-state-cache'= ; from scratch.=C2=A0 This
>=C2=A0 =C2=A0;; will be at the top level, 2 defuns back.=C2=A0 Return n= il if we don't find
>=C2=A0 =C2=A0;; these defun starts a reasonable way back.
>=C2=A0 =C2=A0(message "c-get-fallback-scan-pos")
>=C2=A0 =C2=A0(save-excursion
>=C2=A0 =C2=A0 =C2=A0(save-restriction
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(when (> here (* 10 c-state-cache-too-far= ))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(narrow-to-region (- here (* 10 c-state-cach= e-too-far)) here))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0;; Go back 2 bods, but ignore any bogus posi= tions returned by
>=C2=A0 =C2=A0 =C2=A0 =C2=A0;; beginning-of-defun (i.e. open paren in co= lumn zero).
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char here)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((cnt 2))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(message "beginning-of-defun-loop-00: %= d %d" cnt (point))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(while (not (or (bobp) (zerop cnt)))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(message "beginning-of-defun-loo= p-01: %d" (point))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let (beginning-of-defun-function end= -of-defun-function)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(beginning-of-defun))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(and defun-prompt-regexp
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (looking-at defun-prom= pt-regexp)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (message "beginni= ng-of-defun-loop-02: %d" (point))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (goto-char (match-end = 0)))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(message "beginning-of-defun-loo= p-03: %d" (point))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (eq (char-after) ?\{)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq cnt (1- cnt)))))<= br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0(and (not (bobp))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (point)))))
> ------------------------- snip -------------------------

> That results in the message triple

> ------------------------- snip -------------------------
> beginning-of-defun-loop-01: 5879
> beginning-of-defun-loop-02: 5801
> beginning-of-defun-loop-03: 5879
> beginning-of-defun-loop-01: 5879
> beginning-of-defun-loop-02: 5801
> beginning-of-defun-loop-03: 5879
> ...
> ------------------------- snip -------------------------

> inf-looping.=C2=A0 These points are (|: 5801, ^: 5879) here in P1.java= :

> ------------------------- snip -------------------------
> 178=C2=A0 =C2=A0 } catch (Exception e) {
> 179|=C2=A0 =C2=A0 =C2=A0 error("symTable.addDecl", "une= xpected error with a single HashMap " + e)^;
> 180=C2=A0 =C2=A0 }
> 181
> ------------------------- snip -------------------------

> So the catch-block just before line 181 is recognized as a potential B= OD
> (previous trailing open curly?).=C2=A0 But then `defun-prompt-regexp&#= 39; matches
> the function call in the catch-block as defun prompt regexp (which it<= br> > better should not?), taking point back to where, on next BOD search, t= he
> exact previous BOD is found again.

> So probably there are really two issues here:

> 1. The `defun-prompt-regexp' used by Hyperbole, which matches too<= br> >=C2=A0 =C2=A0 broadly, and

> 2. function `c-get-fallback-scan-pos', which could try harder to a= void
>=C2=A0 =C2=A0 inf-loops when such things happen.

> But that's where I *really* stop here :-)

You've diagnosed the bug completely.=C2=A0 Thanks!=C2=A0 The hang was c= aused
entirely by the loop in c-get-fallback-scan-pos, not the deficiencies in that long regexp.

defun-prompt-regexp, when appended with a \\s( (as is done in
beginning-of-defun-raw) matches the "=C2=A0 =C2=A0 =C2=A0 error("= on L179 of P1.java.
The bare defun-prompt-regexp (as used in CC Mode) matches the entire
line except the terminating ;.=C2=A0 This regexp could do with some
amendment, but it is not the main cause of the bug.

To solve the bug, I'm amending the macro c-beginning-of-defun-1 so that=
it only stops at a debug-prompt-regexp position when it also found a {.
Otherwise it will keep looping until it finds a better position or BOB.

Would all concerned please apply the attached patch to the Emacs master
branch, directory lisp/progmodes.=C2=A0 Then please byte compile CC Mode in=
full (a macro has been changed), and try the result on your real Java
code.=C2=A0 (If anybody wants any help applying the patch or byte compiling= ,
feel free to send me private mail.)=C2=A0 Then please confirm that the bug = is
indeed fixed.=C2=A0 Thanks!

--
Alan Mackenzie (Nuremberg, Germany).

--000000000000e4de1506166a4396--