#1603 Console ErrorList deadlock on error message and wait

closed-fixed
None
5
2012-06-02
2012-05-12
Jarek Czekalski
No

This macro (based on preview javadoc macro) makes jedit hang:

runInSystemShell(view, "echo 'nothing.java:290: error: forced error' && sleep 1 && echo x");
waitForConsole(view);

It is based on linux sleep command, but one may rewrite it using another os commands. The clue is in outputting an error line, to be intercepted by ErrorList plugin, and after a while outputting another line. The deadlock comes from the fact that Console (indirectly through ErrorList) tries to send an EditBus message which waits until EDT thread is available. And EDT thread is blocked by the macro, which waits until Console finishes the command.

I use fresh trunk versions of jedit, Console, ErrorList on Linux. A relevant part of thread dump attached.

Discussion

  •  
    Attachments
  • will69
    will69
    2012-05-23

    This can be reproduced always and it breaks my beanshell scripts. Here are some combinations I tried:

    jEdit 4.3.3 + ErrorList 1.8 + Konsole 4.4.1: OK
    jEdit 4.3.3 + ErrorList 1.9 + Konsole 4.4.1: OK
    jEdit 4.3.3 + ErrorList 1.9 + Konsole 4.4.2: OK
    jEdit 4.4.1 + ErrorList 1.8 + Konsole 4.4.1: deadlock
    jEdit 4.4.1 + ErrorList 1.8 + Konsole 4.4.2: deadlock
    jEdit 4.4.1 + ErrorList 1.9 + Konsole 4.4.2: deadlock
    jEdit 4.4.1 + ErrorList 1.9 + Konsole 4.4.3: deadlock
    jEdit 4.5.1 + ErrorList 1.9 + Konsole 4.5: deadlock
    jEdit 5.0p1+ ErrorList 1.9 + Konsole 4.5: deadlock

    This seems to imply that a change in jEdit itself is responsible for the deadlock. Can somebody fix this, *please*?

     
  • I see 3 approaches to the problem:

    1. Assuming the macro is badly written. In general time-consuming task should not block EDT thread. Invoke waitForConsole(view) inside a worker thread not to block the EDT thread. When it is done, one may go back to the EDT through SwingUtilities.invokeLater

    The side effect is that jedit will probably be operatable while waiting for the command to complete.

    2. Assuming ErrorList bug. Change the message sending code and use sendAsync, after making sure it doesn't break anything. Seems quite easy to do.

    3. Assuming Console bug. Add the ability to invoke complex commands from EDT, probably in one blocking command instead of the pair: run, wait.

    Will, jedit 4.4 introduced a change in handling edit bus messages. That's the clue. I don't know the details, but I guess it was something necessary to achieve synchronization, thread safety and stability.

     
  • will69
    will69
    2012-05-24

    Excellent analysis Jarek! I am somewhat shocked to find out that macros (beanshell scripts) run on the EDT. And they always did! I didn’t expect that. Is there a compelling reason for that?

    Anyway, we have a regression from jEdit 4.3.3, where runInSystemShell() + waitForConsole() could be used to execute an external command synchronously. Now, it doesn’t work any more.

    The most user friendly solution would be to run the whole macro or at least any external commands off the EDT. A combination of runInSystemShell() and waitForConsole() would be fine, too. Something like runInSystemShellAndWait().

    As a workaround, you can wrap your whole macro in a thread:

    new Thread() { public void run() { setName("macro"); macro(); } }.start();

    This works for your case. And for mine, too.

     
  • I found a quote that seems relevant:

    "If you use invokeAndWait(), make sure that the thread that calls invokeAndWait() does not hold any locks that other threads might need while the call is occurring."

    java.sun.com/products/jfc/tsc/articles/threads/threads1.html#event_dispatching
    Under "Using the invokeAndWait() Method" subsection.

    In jedit this remark applies to EditBus.sendTo. This points again to ErrorList. I know that at time of writing ErrorList it was irrelevant, but now it unfortunately is.

    Nice workaround, Will!

     
    • assigned_to: nobody --> jarekczek
     
  • ErrorList does not block (waiting for EDT) since the fix in r21749.

    ErrorList 2.0 will be released only after the release of jEdit 5.0.

    A daily built ErrorList that is to come in a few days may only be used with jEdit >=5.0 (currently it means daily build).

     
    • status: open --> closed-fixed