GNU bug report logs - #37620
26.1; ada-mode 6.2.1 partial parsing occasionally hangs while moving point

Previous Next

Packages: ada-mode, emacs;

Reported by: Ludovic Brenta <ludovic <at> ludovic-brenta.org>

Date: Fri, 4 Oct 2019 13:33:01 UTC

Severity: minor

Found in version 26.1

Done: Stephen Leake <stephen_leake <at> stephe-leake.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 37620 in the body.
You can then email your comments to 37620 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to ada-mode-users <at> nongnu.org, bug-gnu-emacs <at> gnu.org:
bug#37620; Package emacs, ada-mode. (Fri, 04 Oct 2019 13:33:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Brenta <ludovic <at> ludovic-brenta.org>:
New bug report received and forwarded. Copy sent to ada-mode-users <at> nongnu.org, bug-gnu-emacs <at> gnu.org. (Fri, 04 Oct 2019 13:33:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Brenta <ludovic <at> ludovic-brenta.org>
To: bug-gnu-emacs <at> gnu.org
Subject: 26.1; ada-mode 6.2.1 partial parsing occasionally hangs while moving
 point
Date: Fri, 04 Oct 2019 15:31:55 +0200
X-Debbugs-CC: ada-mode-users <at> nongnu.org
Package: emacs, ada-mode
Version: 26.1
Severity: minor

I'm sorry but I cannot trigger this problem reliably.  Occasionally,
while simply moving in a source file (using up, down, page up, page
down etc.), the *Messages* buffer receives these errors:

Error during redisplay: (jit-lock-function 32410) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")
Error during redisplay: (jit-lock-function 32910) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")
Error during redisplay: (jit-lock-function 32940) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")
Error during redisplay: (jit-lock-function 32971) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")
Error during redisplay: (jit-lock-function 32973) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")
Error during redisplay: (jit-lock-function 32988) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")

and the redisplay freezes.  When this happens I usually have to do
M-x wiki-kill-parser to recover.

This happens once every 3-4 days, both on files that are syncatically
correct and on some being edited (I don't think it makes a difference
anymore as the partial parser is in use in both cases).  Has anyone
observed these errors before?  Could it be caused by moving point too
rapidly for the parser process to keep up?

-- 
Ludovic Brenta.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#37620; Package emacs, ada-mode. (Tue, 22 Oct 2019 21:13:02 GMT) Full text and rfc822 format available.

Message #8 received at 37620 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Leake <stephen_leake <at> stephe-leake.org>
To: 37620 <at> debbugs.gnu.org
Subject: update
Date: Tue, 22 Oct 2019 14:11:59 -0700
The error message:

Error during redisplay: (jit-lock-function 32410) signaled (error 
"wisi-process-parse not getting more text (or bad syntax in process 
output)")

indicates that the parser running in the external process is taking too
long to responde, so the elisp interface is timing out.

This can be due to two causes;

1. the code has a syntax error that is particularly hard to correct

2. the computer is otherwise loaded, so the parser is running slowly.

Since you report it happening in several files at different places,
cause 1. is not likely.

You can try increasing wisi-process-time-out (default 5 seconds); that
is how long the elisp interace waits for the external parser.

I'll change the error message to mention wisi-process-time-out.

-- 
-- Stephe




Information forwarded to bug-gnu-emacs <at> gnu.org, stephen_leake <at> stephe-leake.org:
bug#37620; Package emacs, ada-mode. (Tue, 19 Nov 2019 14:53:01 GMT) Full text and rfc822 format available.

Message #11 received at 37620 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Brenta <ludovic <at> ludovic-brenta.org>
To: 37620 <at> debbugs.gnu.org
Subject: Re: 26.1; ada-mode 6.2.1 partial parsing occasionally hangs while
 moving point
Date: Tue, 19 Nov 2019 15:52:33 +0100
No, the machine is not particularly loaded.  I believe the most
likely cause is "the code has a syntax error that is particularly
hard to correct"; but this is only because of partial parsing as
the entire file is syntactically correct.

I'll send you the next source file where this happens; maybe
you can reproduce.

Increasing wisi-process-time-out to more than 5 seconds does not
seem like a solution to me; parsing the entire buffer (resulting in
no syntax errors, no attempted recovery and no time-out) takes
less than that.  Also, since we are only moving point in an
unmodified buffer, interactive use requires 0.1 s response time or
less.  Therefore, perhaps a solution would be to /decrease/
wisi-process-time-out and automatically launch a full parse
whenever it happens; as long as the buffer remains unmodified, no
re-parsing will take place.

-- 
Ludovic Brenta.




Information forwarded to bug-gnu-emacs <at> gnu.org, stephen_leake <at> stephe-leake.org:
bug#37620; Package emacs, ada-mode. (Tue, 19 Nov 2019 15:03:02 GMT) Full text and rfc822 format available.

Message #14 received at 37620 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Brenta <ludovic <at> ludovic-brenta.org>
To: 37620 <at> debbugs.gnu.org
Subject: Re: 26.1; ada-mode 6.2.1 partial parsing occasionally hangs while
 moving point
Date: Tue, 19 Nov 2019 16:02:03 +0100
Triggering this bug is much easier when you jump into the
middle of a file using cross-references from another file
or etags, as opposed to opening the file at the beginning
and then scrolling.  Because if you simply visit a file
(even a large one), partial parsing starts from the beginning
of the file and has a much lower chance of finding syntax
errors.

-- 
Ludovic Brenta.




Information forwarded to bug-gnu-emacs <at> gnu.org, stephen_leake <at> stephe-leake.org:
bug#37620; Package emacs, ada-mode. (Tue, 03 Mar 2020 22:30:02 GMT) Full text and rfc822 format available.

Message #17 received at 37620 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Leake <stephen_leake <at> stephe-leake.org>
To: 37620 <at> debbugs.gnu.org
Subject: 26.1;
 ada-mode 6.2.1 partial parsing occasionally hangs while moving point
Date: Tue, 03 Mar 2020 14:29:14 -0800
[Message part 1 (text/plain, inline)]
There is a bug in error recovery that can cause the parser to hang; that
may be the cause of this bug.

Patch attached.
-- 
-- Stephe
[patch.diff (text/x-patch, inline)]
--- a/wisitoken-parse-lr-mckenzie_recover-base.adb
+++ b/wisitoken-parse-lr-mckenzie_recover-base.adb
@@ -2,7 +2,7 @@
 --
 --  Base utilities for McKenzie_Recover
 --
---  Copyright (C) 2018, 2019 Free Software Foundation, Inc.
+--  Copyright (C) 2018 - 2020 Free Software Foundation, Inc.
 --
 --  This library is free software;  you can redistribute it and/or modify it
 --  under terms of the  GNU General Public License  as published by the Free
@@ -30,49 +30,56 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Base is
      return Boolean
    is
       Done_Count : SAL.Base_Peek_Type := 0;
+      Skip : Boolean;
    begin
       --  Return True if all parsers are done, or if any parser has a config
       --  available to check.
       for P_Status of Parser_Status loop
+         Skip := False;
+
          case P_Status.Recover_State is
          when Active | Ready =>
             if P_Status.Parser_State.Recover.Config_Heap.Count > 0 then
                if P_Status.Parser_State.Recover.Check_Count - Check_Delta_Limit >= Min_Success_Check_Count then
                   --  fail; another parser succeeded, this one taking too long.
                   Done_Count := Done_Count + 1;
+                  Skip := True;
 
                elsif Total_Enqueue_Count + P_Status.Parser_State.Recover.Config_Full_Count >= Enqueue_Limit then
                   --  fail
                   Done_Count := Done_Count + 1;
+                  Skip := True;
                end if;
             end if;
 
-            case P_Status.Recover_State is
-            when Active =>
-               if P_Status.Parser_State.Recover.Config_Heap.Count > 0 then
-                  --  Still working
-                  return True;
-               else
-                  if P_Status.Active_Workers = 0 then
-                     --  fail; no configs left to check.
-                     Done_Count := Done_Count + 1;
+            if not Skip then
+               case P_Status.Recover_State is
+               when Active =>
+                  if P_Status.Parser_State.Recover.Config_Heap.Count > 0 then
+                     --  Still working
+                     return True;
+                  else
+                     if P_Status.Active_Workers = 0 then
+                        --  fail; no configs left to check.
+                        Done_Count := Done_Count + 1;
+                     end if;
                   end if;
-               end if;
 
-            when Ready =>
-               if P_Status.Parser_State.Recover.Config_Heap.Count > 0 and then
-                 P_Status.Parser_State.Recover.Config_Heap.Min_Key <= P_Status.Parser_State.Recover.Results.Min_Key
-               then
-                  --  Still more to check.
-                  return True;
+               when Ready =>
+                  if P_Status.Parser_State.Recover.Config_Heap.Count > 0 and then
+                    P_Status.Parser_State.Recover.Config_Heap.Min_Key <= P_Status.Parser_State.Recover.Results.Min_Key
+                  then
+                     --  Still more to check.
+                     return True;
 
-               elsif P_Status.Active_Workers = 0 then
-                  Done_Count := Done_Count + 1;
-               end if;
+                  elsif P_Status.Active_Workers = 0 then
+                     Done_Count := Done_Count + 1;
+                  end if;
 
-            when others =>
-               null;
-            end case;
+               when others =>
+                  null;
+               end case;
+            end if;
 
          when Success | Fail =>
             Done_Count := Done_Count + 1;
@@ -135,6 +142,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Base is
           (Parsers, Parser_Status, Min_Success_Check_Count, Total_Enqueue_Count, Check_Delta_Limit, Enqueue_Limit)
       is
          Done_Count     : SAL.Base_Peek_Type := 0;
+         Skip           : Boolean;
          Min_Cost       : Integer            := Integer'Last;
          Min_Cost_Index : SAL.Base_Peek_Type;
 
@@ -168,6 +176,8 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Base is
          --  No task_id in outline trace messages, because they may appear in
          --  .parse_good
          for I in Parser_Status'Range loop
+            Skip := False;
+
             declare
                P_Status : Base.Parser_Status renames Parser_Status (I);
             begin
@@ -186,6 +196,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Base is
                         P_Status.Fail_Mode     := Fail_Check_Delta;
 
                         Done_Count := Done_Count + 1;
+                        Skip := True;
 
                      elsif Total_Enqueue_Count + P_Status.Parser_State.Recover.Config_Full_Count >= Enqueue_Limit then
                         if Trace_McKenzie > Outline then
@@ -200,48 +211,51 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Base is
                         P_Status.Fail_Mode     := Fail_Enqueue_Limit;
 
                         Done_Count := Done_Count + 1;
+                        Skip := True;
                      end if;
                   end if;
 
-                  case P_Status.Recover_State is
-                  when Active =>
-                     if P_Status.Parser_State.Recover.Config_Heap.Count > 0 then
-                        if P_Status.Parser_State.Recover.Config_Heap.Min_Key < Min_Cost then
-                           Min_Cost       := P_Status.Parser_State.Recover.Config_Heap.Min_Key;
-                           Min_Cost_Index := I;
-                           --  not done
-                        end if;
-                     else
-                        if P_Status.Active_Workers = 0 then
-                           --  No configs left to check (rarely happens with real languages).
-                           if Trace_McKenzie > Outline then
-                              Put_Line
-                                (Trace.all, P_Status.Parser_State.Label, "fail; no configs left", Task_ID => False);
+                  if not Skip then
+                     case P_Status.Recover_State is
+                     when Active =>
+                        if P_Status.Parser_State.Recover.Config_Heap.Count > 0 then
+                           if P_Status.Parser_State.Recover.Config_Heap.Min_Key < Min_Cost then
+                              Min_Cost       := P_Status.Parser_State.Recover.Config_Heap.Min_Key;
+                              Min_Cost_Index := I;
+                              --  not done
+                           end if;
+                        else
+                           if P_Status.Active_Workers = 0 then
+                              --  No configs left to check (rarely happens with real languages).
+                              if Trace_McKenzie > Outline then
+                                 Put_Line
+                                   (Trace.all, P_Status.Parser_State.Label, "fail; no configs left", Task_ID => False);
+                              end if;
+                              P_Status.Recover_State := Fail;
+                              P_Status.Fail_Mode     := Fail_No_Configs_Left;
+
+                              Done_Count := Done_Count + 1;
                            end if;
-                           P_Status.Recover_State := Fail;
-                           P_Status.Fail_Mode     := Fail_No_Configs_Left;
-
-                           Done_Count := Done_Count + 1;
                         end if;
-                     end if;
 
-                  when Ready =>
-                     if P_Status.Parser_State.Recover.Config_Heap.Count > 0 and then
-                       P_Status.Parser_State.Recover.Config_Heap.Min_Key <=
-                       P_Status.Parser_State.Recover.Results.Min_Key
-                     then
-                        --  Still more to check. We don't check Min_Cost here so this parser
-                        --  can finish quickly.
-                        Set_Outputs (I);
-                        return;
-
-                     elsif P_Status.Active_Workers = 0 then
-                        P_Status.Recover_State := Success;
-                        Done_Count             := Done_Count + 1;
-                     end if;
-                  when others =>
-                     null;
-                  end case;
+                     when Ready =>
+                        if P_Status.Parser_State.Recover.Config_Heap.Count > 0 and then
+                          P_Status.Parser_State.Recover.Config_Heap.Min_Key <=
+                          P_Status.Parser_State.Recover.Results.Min_Key
+                        then
+                           --  Still more to check. We don't check Min_Cost here so this parser
+                           --  can finish quickly.
+                           Set_Outputs (I);
+                           return;
+
+                        elsif P_Status.Active_Workers = 0 then
+                           P_Status.Recover_State := Success;
+                           Done_Count             := Done_Count + 1;
+                        end if;
+                     when others =>
+                        null;
+                     end case;
+                  end if;
 
                when Success | Fail =>
                   Done_Count := Done_Count + 1;

Added tag(s) pending. Request was from Stephen Leake <stephen_leake <at> stephe-leake.org> to control <at> debbugs.gnu.org. (Wed, 22 Apr 2020 18:19:02 GMT) Full text and rfc822 format available.

Reply sent to Stephen Leake <stephen_leake <at> stephe-leake.org>:
You have taken responsibility. (Sun, 07 Jun 2020 21:26:01 GMT) Full text and rfc822 format available.

Notification sent to Ludovic Brenta <ludovic <at> ludovic-brenta.org>:
bug acknowledged by developer. (Sun, 07 Jun 2020 21:26:02 GMT) Full text and rfc822 format available.

Message #24 received at 37620-close <at> debbugs.gnu.org (full text, mbox):

From: Stephen Leake <stephen_leake <at> stephe-leake.org>
To: 37620-close <at> debbugs.gnu.org
Subject: closed by ada-mode version 7.1.3
Date: Sun, 07 Jun 2020 14:25:19 -0700
-- 
-- Stephe




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 06 Jul 2020 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 288 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.