Changeset 34234


Ignore:
Timestamp:
2020-07-01T03:26:12+12:00 (4 years ago)
Author:
ak19
Message:

Bugfix I think for the deadlock issue that can occur when a GUI task on client-GLI's remote action queue results in an error attempting to produce a popup also run on the GUI thread. showMessageDialog() for error msgs now wrapped in a SwingUtilities.invokeLater(). This does seem to have fixed the deadlock for the exact example case I encountered, which was the issue fixed in commit revision 34232.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/remote/ActionQueue.java

    r34153 r34234  
    7979    }
    8080   
    81     // We often end up with giant blotted remote build error messages when things blow up
    82     // These messages appear in pop ups that take up the entire screen and we can't even see the OK button
    83     // This method therefore adds a scrollPane around error messages when displaying them.
    84     // https://alvinalexander.com/java/joptionpane-showmessagedialog-example-scrolling/
    85     private JScrollPane getMsgInScrollPane(String msg) {
    86     // create a JTextArea
    87     JTextArea textArea = new JTextArea(20, 70);
    88     textArea.setText(msg);
    89     textArea.setEditable(false);
    90     // wrap a scrollpane around message
    91     JScrollPane scrollPane = new JScrollPane(textArea);
    92     return scrollPane;
    93     }
    9481   
    9582    synchronized public void addAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
     
    161148            DebugStream.printStackTrace(exception);
    162149        }
    163         JScrollPane scrollPane = getMsgInScrollPane(Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()));
    164         JOptionPane.showMessageDialog(Gatherer.g_man, scrollPane, Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
     150        RemoteErrorPopup.invokeLater(exception.getMessage());
    165151        remote_greenstone_server_action.processed_successfully = false;         
    166152        }
     
    170156        exit = true;
    171157        DebugStream.printStackTrace(exception);
    172         JScrollPane scrollPane = getMsgInScrollPane(Dictionary.get("RemoteGreenstoneServer.Error",
    173                                  "No gliserver.pl found. " + exception.getMessage()));
    174         JOptionPane.showMessageDialog(Gatherer.g_man,
    175                           scrollPane,
    176                           Dictionary.get("RemoteGreenstoneServer.Error_Title"),
    177                           JOptionPane.ERROR_MESSAGE);
     158        RemoteErrorPopup.invokeLater("No gliserver.pl found. " + exception.getMessage());
    178159        remote_greenstone_server_action.processed_successfully = false;
    179160        }
    180161        catch (Exception exception) {
    181162        DebugStream.printStackTrace(exception);
    182         JScrollPane scrollPane = getMsgInScrollPane(Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()));
    183         JOptionPane.showMessageDialog(Gatherer.g_man, scrollPane, Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
     163        RemoteErrorPopup.invokeLater(exception.getMessage());
    184164        remote_greenstone_server_action.processed_successfully = false;
    185165        }
     
    208188    }
    209189    }
     190
     191   
     192    // When deadlock, referred to in Kathy's commit comments as stalemate, occurs during a RemoteGS threaded
     193    // task run on a queue, and this task is a GUI one and on the GUI thread, such as launching GEMS from the
     194    // MetadataSetManager to create/edit a metadata set, any remote errors that then cause error dialogs to
     195    // pop up result in a deadlock between the widgets since there's waiting going on for the first widget.
     196    // This prevents the second widget from showing or working right, as both are on the same (GUI) thread.
     197    // As end result, client-GLI freezes.
     198    // An example of such an error that caused an error message to popup resulting in a GUI deadlock was
     199    // fixed in commit http://trac.greenstone.org/changeset/34232 (client-GLI > MetadataSetManager > GEMS)
     200    // But in theory such a GUI deadlock could happen for as yet unfixed errors. It prevents us from even
     201    // reading the error msg in the popup and delays debugging. What we need is to show the popup when
     202    // the GUI thread is free, i.e. SwingUtilities.invokeLater() stuff.
     203    // Private inner class RemoteErrorPopup deals with that. Refer to:
     204    // - https://stackoverflow.com/questions/1595744/is-joptionpane-showmessagedialog-thread-safe
     205    //   "JOptionPane does not document that it is thread safe, so you have to use invokeLater()."
     206    //   Also contains SwingWorker-based idea for the GUI thread clash between OpenCollDialog and
     207    // ProgressBar during automated Greenstone GUI testing.
     208    // - https://stackoverflow.com/questions/13863713/which-thread-to-launch-joptionpane
     209    // - https://www.codota.com/code/java/methods/javax.swing.JOptionPane/showMessageDialog
     210    // - https://www.programcreek.com/java-api-examples/?class=javax.swing.SwingUtilities&method=invokeLater
     211    private static class RemoteErrorPopup implements Runnable {
     212
     213    /** Custom static method to make a safely threaded popup easier to call */
     214    public static void invokeLater(String msg) {
     215        SwingUtilities.invokeLater(new RemoteErrorPopup(msg));
     216    }
     217
     218   
     219    private String message;
     220   
     221    private RemoteErrorPopup(String msg) {
     222        message = msg;
     223    }
     224
     225       
     226    @Override
     227    public void run() {
     228       
     229        String msg = Dictionary.get("RemoteGreenstoneServer.Error", message);
     230
     231        // We often end up with giant bloated remote build error messages when things blow up
     232        // These messages appear in pop ups that take up the entire screen and we can't even see the OK button
     233        // The following therefore adds a scrollPane around error messages shown in showMessageDialog
     234        // https://alvinalexander.com/java/joptionpane-showmessagedialog-example-scrolling/
     235        JTextArea textArea = new JTextArea(20, 70);
     236        textArea.setText(msg);
     237        textArea.setEditable(false);
     238        // wrap a scrollpane around message
     239        JScrollPane scrollPane = new JScrollPane(textArea);     
     240       
     241        JOptionPane.showMessageDialog(Gatherer.g_man, scrollPane, Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
     242    }   
     243    }
     244   
    210245}
     246
     247
Note: See TracChangeset for help on using the changeset viewer.