@@ -89,6 +89,8 @@ public class SwingConsolePane extends AbstractConsolePane<JPanel> {
8989
9090 private JPanel component ;
9191
92+ private boolean initializing ;
93+
9294 public SwingConsolePane (final Context context ) {
9395 super (context );
9496 }
@@ -127,7 +129,7 @@ public void run() {
127129
128130 @ Override
129131 public JPanel getComponent () {
130- if (consolePanel == null ) initLoggingPanel ();
132+ if (consolePanel == null ) initComponents ();
131133 return component ;
132134 }
133135
@@ -139,12 +141,58 @@ public Class<JPanel> getComponentType() {
139141 // -- Helper methods - lazy initialization --
140142
141143 private ConsolePanel consolePanel () {
142- if (consolePanel == null ) initLoggingPanel ();
144+ if (consolePanel == null ) initComponents ();
143145 return consolePanel ;
144146 }
145147
146- private synchronized void initLoggingPanel () {
148+ private synchronized void initComponents () {
147149 if (consolePanel != null ) return ;
150+ if (initializing ) {
151+ // NB: We are in a loop, with `new ConsolePanel` triggering more output.
152+ //
153+ // In a nutshell:
154+ // stderr -> ConsoleService -> new ConsolePanel -> stderr -> ...
155+ //
156+ // Here is an example where we have experienced this happening:
157+ //
158+ // ...
159+ // at org.scijava.ui.swing.console.ConsolePanel.<init>(...)
160+ // at org.scijava.ui.swing.console.SwingConsolePane.initComponents(...)
161+ // at org.scijava.ui.swing.console.SwingConsolePane.consolePanel(...)
162+ // at org.scijava.ui.swing.console.SwingConsolePane.append(...)
163+ // at org.scijava.ui.console.AbstractConsolePane.outputOccurred(...)
164+ // at org.scijava.console.DefaultConsoleService.notifyListeners(...)
165+ // at org.scijava.console.DefaultConsoleService$OutputStreamReporter.publish(...)
166+ // at org.scijava.console.DefaultConsoleService$OutputStreamReporter.write(...)
167+ // at org.scijava.console.MultiOutputStream.write(...)
168+ // at java.io.PrintStream.write(...)
169+ // ...
170+ // at java.lang.Throwable.printStackTrace(...)
171+ // at javax.swing.UIDefaults.getUIError(...)
172+ // at javax.swing.MultiUIDefaults.getUIError(...)
173+ // at javax.swing.UIDefaults.getUI(...)
174+ // at javax.swing.UIManager.getUI(...)
175+ // at javax.swing.text.JTextComponent.updateUI(...)
176+ // at javax.swing.text.JTextComponent.<init>(...)
177+ // at javax.swing.JEditorPane.<init>(...)
178+ // at javax.swing.JTextPane.<init>(...)
179+ // at org.scijava.ui.swing.console.ConsolePanel.initGui(...)
180+ // at org.scijava.ui.swing.console.ConsolePanel.<init>(...)
181+ // at org.scijava.ui.swing.console.SwingConsolePane.initComponents(...)
182+ // at org.scijava.ui.swing.console.SwingConsolePane.consolePanel(...)
183+ // at org.scijava.ui.swing.console.SwingConsolePane.append(...)
184+ // at org.scijava.ui.console.AbstractConsolePane.outputOccurred(...)
185+ // at org.scijava.console.DefaultConsoleService.notifyListeners(...)
186+ // at org.scijava.console.DefaultConsoleService$OutputStreamReporter.publish(...)
187+ // at org.scijava.console.DefaultConsoleService$OutputStreamReporter.write(...)
188+ // at org.scijava.console.MultiOutputStream.write(...)
189+ // at java.io.PrintStream.write(...)
190+ // ...
191+ //
192+ throw new RuntimeException (
193+ "Output loop while initializing the console GUI." );
194+ }
195+ initializing = true ;
148196 consolePanel = new ConsolePanel (context );
149197 loggingPanel = new LoggingPanel (context , LOG_FORMATTING_SETTINGS_KEY );
150198 logService .addLogListener (loggingPanel );
@@ -153,6 +201,7 @@ private synchronized void initLoggingPanel() {
153201 tabs .addTab ("Console" , consolePanel );
154202 tabs .addTab ("Log" , loggingPanel );
155203 component .add (tabs , "grow" );
204+ initializing = false ;
156205 }
157206
158207 // -- Helper methods - testing --
0 commit comments