Random UI freezes because of never ending `IOConsolePartitioner...processPendingPartitions`
Let's make sure issue is not already fixed in latest builds first.
- [ ] I verified I can reproduce this issue against latest Integration Build of Eclipse SDK
Steps to reproduce
I don't know, the freezes happen randomly. I have not seen a common pattern. I noticed the issue since upgrading to Eclipse 2025-09
I expected: The UI not permanently freeze
But got: Eclipse does not respond, I have to kill the process
Here is some relevant log output
From <workspace>/.metadata/.log
!ENTRY org.eclipse.ui.monitoring 2 0 2025-11-17 17:58:47.323
!MESSAGE UI freeze of 27s at 17:58:20.373
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-11-17 17:58:47.323
!MESSAGE Sample at 17:58:31.030 (+10,657s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
at org.eclipse.swt.internal.win32.OS.ScriptShape(Native Method)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3674)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3760)
at org.eclipse.swt.graphics.TextLayout.computeRuns(TextLayout.java:513)
at org.eclipse.swt.graphics.TextLayout.getBounds(TextLayout.java:1793)
at org.eclipse.swt.custom.StyledTextRenderer.calculate(StyledTextRenderer.java:307)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:758)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:749)
at org.eclipse.swt.custom.StyledText.getLinePixel(StyledText.java:3906)
at org.eclipse.swt.custom.StyledText.handleTextChanging(StyledText.java:6156)
at org.eclipse.swt.custom.StyledText$5.textChanging(StyledText.java:5438)
at org.eclipse.ui.internal.console.ConsoleDocumentAdapter.documentAboutToBeChanged(ConsoleDocumentAdapter.java:418)
at org.eclipse.jface.text.AbstractDocument.fireDocumentAboutToBeChanged(AbstractDocument.java:636)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1082)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1109)
at org.eclipse.ui.internal.console.ConsoleDocument.replace(ConsoleDocument.java:74)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyOutputToDocument(IOConsolePartitioner.java:1145)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyStreamOutput(IOConsolePartitioner.java:968)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.processPendingPartitions(IOConsolePartitioner.java:805)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.runInUIThread(IOConsolePartitioner.java:763)
at org.eclipse.ui.progress.UIJob.lambda$0(UIJob.java:148)
at org.eclipse.ui.progress.UIJob$$Lambda/0x00000007c0f18800.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4135)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3751)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:678)
at org.eclipse.ui.internal.Workbench$$Lambda/0x00000007c033fc70.run(Unknown Source)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
at [email protected]/java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(DirectMethodHandle$Holder)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018d800.invoke(LambdaForm$MH)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018dc00.invokeExact_MT(LambdaForm$MH)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:155)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at [email protected]/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:627)
at app//org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at app//org.eclipse.equinox.launcher.Main.run(Main.java:1431)
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-11-17 17:58:47.323
!MESSAGE Sample at 17:58:36.358 (+5,328s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
at org.eclipse.swt.internal.win32.OS.ScriptShape(Native Method)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3674)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3760)
at org.eclipse.swt.graphics.TextLayout.computeRuns(TextLayout.java:513)
at org.eclipse.swt.graphics.TextLayout.getBounds(TextLayout.java:1793)
at org.eclipse.swt.custom.StyledTextRenderer.calculate(StyledTextRenderer.java:307)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:758)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:749)
at org.eclipse.swt.custom.StyledText.getLinePixel(StyledText.java:3906)
at org.eclipse.swt.custom.StyledText.handleTextChanging(StyledText.java:6156)
at org.eclipse.swt.custom.StyledText$5.textChanging(StyledText.java:5438)
at org.eclipse.ui.internal.console.ConsoleDocumentAdapter.documentAboutToBeChanged(ConsoleDocumentAdapter.java:418)
at org.eclipse.jface.text.AbstractDocument.fireDocumentAboutToBeChanged(AbstractDocument.java:636)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1082)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1109)
at org.eclipse.ui.internal.console.ConsoleDocument.replace(ConsoleDocument.java:74)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyOutputToDocument(IOConsolePartitioner.java:1145)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyStreamOutput(IOConsolePartitioner.java:968)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.processPendingPartitions(IOConsolePartitioner.java:805)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.runInUIThread(IOConsolePartitioner.java:763)
at org.eclipse.ui.progress.UIJob.lambda$0(UIJob.java:148)
at org.eclipse.ui.progress.UIJob$$Lambda/0x00000007c0f18800.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4135)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3751)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:678)
at org.eclipse.ui.internal.Workbench$$Lambda/0x00000007c033fc70.run(Unknown Source)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
at [email protected]/java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(DirectMethodHandle$Holder)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018d800.invoke(LambdaForm$MH)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018dc00.invokeExact_MT(LambdaForm$MH)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:155)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at [email protected]/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:627)
at app//org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at app//org.eclipse.equinox.launcher.Main.run(Main.java:1431)
...
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-11-17 18:02:22.371
!MESSAGE Sample at 18:02:13.451 (+10,657s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
at org.eclipse.swt.internal.win32.OS.ScriptShape(Native Method)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3674)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3760)
at org.eclipse.swt.graphics.TextLayout.computeRuns(TextLayout.java:513)
at org.eclipse.swt.graphics.TextLayout.getBounds(TextLayout.java:1793)
at org.eclipse.swt.custom.StyledTextRenderer.calculate(StyledTextRenderer.java:307)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:758)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:749)
at org.eclipse.swt.custom.StyledText.getLinePixel(StyledText.java:3906)
at org.eclipse.swt.custom.StyledText.handleTextChanging(StyledText.java:6156)
at org.eclipse.swt.custom.StyledText$5.textChanging(StyledText.java:5438)
at org.eclipse.ui.internal.console.ConsoleDocumentAdapter.documentAboutToBeChanged(ConsoleDocumentAdapter.java:418)
at org.eclipse.jface.text.AbstractDocument.fireDocumentAboutToBeChanged(AbstractDocument.java:636)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1082)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1109)
at org.eclipse.ui.internal.console.ConsoleDocument.replace(ConsoleDocument.java:74)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyOutputToDocument(IOConsolePartitioner.java:1145)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyStreamOutput(IOConsolePartitioner.java:968)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.processPendingPartitions(IOConsolePartitioner.java:805)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.runInUIThread(IOConsolePartitioner.java:763)
at org.eclipse.ui.progress.UIJob.lambda$0(UIJob.java:148)
at org.eclipse.ui.progress.UIJob$$Lambda/0x00000007c0f18800.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4135)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3751)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:678)
at org.eclipse.ui.internal.Workbench$$Lambda/0x00000007c033fc70.run(Unknown Source)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
at [email protected]/java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(DirectMethodHandle$Holder)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018d800.invoke(LambdaForm$MH)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018dc00.invokeExact_MT(LambdaForm$MH)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:155)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at [email protected]/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:627)
at app//org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at app//org.eclipse.equinox.launcher.Main.run(Main.java:1431)
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-11-17 18:02:22.371
!MESSAGE Sample at 18:02:18.778 (+5,327s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
at org.eclipse.swt.internal.win32.OS.ScriptShape(Native Method)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3674)
at org.eclipse.swt.graphics.TextLayout.shape(TextLayout.java:3760)
at org.eclipse.swt.graphics.TextLayout.computeRuns(TextLayout.java:513)
at org.eclipse.swt.graphics.TextLayout.getBounds(TextLayout.java:1793)
at org.eclipse.swt.custom.StyledTextRenderer.calculate(StyledTextRenderer.java:307)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:758)
at org.eclipse.swt.custom.StyledTextRenderer.getLineHeight(StyledTextRenderer.java:749)
at org.eclipse.swt.custom.StyledText.getLinePixel(StyledText.java:3906)
at org.eclipse.swt.custom.StyledText.handleTextChanging(StyledText.java:6156)
at org.eclipse.swt.custom.StyledText$5.textChanging(StyledText.java:5438)
at org.eclipse.ui.internal.console.ConsoleDocumentAdapter.documentAboutToBeChanged(ConsoleDocumentAdapter.java:418)
at org.eclipse.jface.text.AbstractDocument.fireDocumentAboutToBeChanged(AbstractDocument.java:636)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1082)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1109)
at org.eclipse.ui.internal.console.ConsoleDocument.replace(ConsoleDocument.java:74)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyOutputToDocument(IOConsolePartitioner.java:1145)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyStreamOutput(IOConsolePartitioner.java:968)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.processPendingPartitions(IOConsolePartitioner.java:805)
at org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.runInUIThread(IOConsolePartitioner.java:763)
at org.eclipse.ui.progress.UIJob.lambda$0(UIJob.java:148)
at org.eclipse.ui.progress.UIJob$$Lambda/0x00000007c0f18800.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4135)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3751)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:678)
at org.eclipse.ui.internal.Workbench$$Lambda/0x00000007c033fc70.run(Unknown Source)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
at [email protected]/java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(DirectMethodHandle$Holder)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018d800.invoke(LambdaForm$MH)
at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000007c018dc00.invokeExact_MT(LambdaForm$MH)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:155)
at [email protected]/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at [email protected]/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:627)
at app//org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at app//org.eclipse.equinox.launcher.Main.run(Main.java:1431)
Tested under this environment:
- OS & version: Windows 10
- Eclipse IDE/Platform version (as shown in Help > About): Version: 2025-09 (4.37.0) Build id: 20250905-1456
Community
- [/] I understand reporting an issue to this OSS project does not mandate anyone to fix it. Other contributors may consider the issue, or not, at their own convenience. The most efficient way to get it fixed is that I fix it myself and contribute it back as a good quality patch to the project.
I let codex (gpt 5.1 high) analyze the issue:
UI freeze involving IOConsolePartitioner and console text layout
1. Evidence from workspace.log
- The log in
workspace.logreports a UI freeze of ~31 seconds:-
!ENTRY org.eclipse.ui.monitoring 2 0 2025-11-17 18:00:18.276 -
!MESSAGE UI freeze of 31s at 17:59:47.709
-
- Samples during the freeze show the main UI thread (
Thread 'main' tid=1 (RUNNABLE)) busy, not blocked on a lock. - Representative sampled stack (abridged):
-
org.eclipse.swt.internal.win32.OS.ScriptShape / ScriptGetLogicalWidths / ScriptBreak -
org.eclipse.swt.graphics.TextLayout.computeRuns / getBounds -
org.eclipse.swt.custom.StyledTextRenderer.calculate / getLineHeight -
org.eclipse.swt.custom.StyledText.handleTextChanging -
org.eclipse.swt.custom.StyledText$5.textChanging -
org.eclipse.ui.internal.console.ConsoleDocumentAdapter.documentAboutToBeChanged(ConsoleDocumentAdapter.java:418) -
org.eclipse.jface.text.AbstractDocument.replace(...) -
org.eclipse.ui.internal.console.ConsoleDocument.replace(...) -
org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyOutputToDocument(IOConsolePartitioner.java:1145) -
org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.applyStreamOutput(IOConsolePartitioner.java:968) -
org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.processPendingPartitions(IOConsolePartitioner.java:805) -
org.eclipse.ui.internal.console.IOConsolePartitioner$QueueProcessingJob.runInUIThread(IOConsolePartitioner.java:763) - SWT event loop / workbench run loop.
-
Conclusion: the UI thread is CPU-bound inside SWT text layout invoked as part of console document updates triggered by IOConsolePartitioner.QueueProcessingJob.
2. Relevant code in this repository
2.1 IOConsolePartitioner (debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java)
- Maintains console partitions and a bounded queue of pending output:
-
MAX_BUFFER_BYTES = 16_000_000(approx 16 MB). -
BlockingQueue<PendingPartition> pendingPartitions = new LinkedBlockingQueue<>(MAX_BUFFER_BYTES / 8192); - Comment: up to ~16 MB pending when the debuggee produces output faster than it can be processed.
-
- Output from streams is enqueued via:
-
public void streamAppended(IOConsoleOutputStream stream, String s)- Wraps text in
PendingPartitionandoffers intopendingPartitions. - On failure, calls
helpProgress(); if called on the UI thread (Display.getCurrent() != null), it directly callsqueueJob.processPendingPartitions(). - Schedules
queueJobafter enqueuing.
- Wraps text in
-
-
QueueProcessingJobis aUIJob:-
public IStatus runInUIThread(IProgressMonitor monitor)callsprocessPendingPartitions(). -
processPendingPartitions():- Drains the entire queue into a local list:
pendingPartitions.drainTo(pendingCopy);. - Under
synchronized (partitions):- Calls
applyStreamOutput(pendingCopy, sizeHint); - Then
checkFinished(); - Then
checkBufferSize();(trimming if high-water mark is exceeded).
- Calls
- Drains the entire queue into a local list:
-
-
applyStreamOutput(...):- Runs entirely under the
partitionslock and on the UI thread. - Iterates all
PendingPartitions, interprets control characters, computes partition updates, and accumulates text into aStringBuilder content. - Calls
applyOutputToDocument(content.toString(), nextWriteOffset, replaceLength)at various points and once at the end.
- Runs entirely under the
-
applyOutputToDocument(...):- Sets
updateType = DocUpdateType.OUTPUT. - Executes
document.replace(offset, length, text)(JFace document API). - This
replacetriggersConsoleDocumentAdapter.documentAboutToBeChanged, which in turn firesTextChangingEventtoStyledText, causing expensive SWTTextLayoutrecalculation.
- Sets
2.2 Console buffer trimming
- High/low watermark configuration:
- In
IOConsole(debug/org.eclipse.ui.console/src/org/eclipse/ui/console/IOConsole.java),setWaterMarks(int low, int high)validates and forwards to the partitioner:-
partitioner.setWaterMarks(low, high);
-
- In
IOConsolePartitioner.setWaterMarks(...):- Stores
lowWaterMarkandhighWaterMark. - Schedules
checkBufferSize()viaConsolePlugin.getStandardDisplay().asyncExec(this::checkBufferSize);.
- Stores
- In
-
checkBufferSize():- If
document != null && highWaterMark > 0anddocument.getLength() > highWaterMark:- Calls
trim(length - lowWaterMark, true);synchronously in the UI thread.
- Calls
- If
-
trim(...):- Uses
document.getLineOfOffset(...)/getLineOffset(...)to find the cut position. - Either clears the whole document or:
- Adjusts the first partition and then
document.replace(0, cutOffset, ""). - Rebuilds partition offsets and adjusts
outputOffset.
- Adjusts the first partition and then
- All of this runs under
synchronized (partitions)and on the UI thread, again invoking StyledText text layout.
- Uses
- Debug consoles (
ProcessConsole) configure watermarks from user preferences:- In
ProcessConsole.init():- If
CONSOLE_LIMIT_CONSOLE_OUTPUTis true, callssetWaterMarks(lowWater, highWater). - If the preference is false, it calls
setWaterMarks(-1, -1), which disables trimming (highWaterMarkremains negative).
- If
- In
2.3 ConsoleDocumentAdapter
-
ConsoleDocumentAdapter(debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java) bridges the JFace document and SWTStyledText. -
documentAboutToBeChanged(DocumentEvent event)builds aTextChangingEventand notifiesTextChangeListeners (includingStyledText):- This drives
StyledText.handleTextChanging(...)and ultimatelyTextLayout(computeRuns,getBounds, etc), which is exactly what appears on the hot stack frames in the freeze sampling.
- This drives
- In fixed-width / wrapping mode,
ConsoleDocumentAdapterdoes extra work to recompute wrapped lines, which amplifies the cost of each document change for large documents.
3. Analysis of the freeze
- The freeze is not a deadlock but a long CPU-bound operation on the main UI thread.
- The thread state is
RUNNABLEwith hot frames insideOS.ScriptShape/ScriptGetLogicalWidths/ScriptBreak, indicating heavy text shaping and layout.
- The thread state is
- The call chain ties the expensive layout directly to console output processing:
-
IOConsolePartitioner$QueueProcessingJob.runInUIThread→processPendingPartitions→applyStreamOutput→applyOutputToDocument→document.replace→ConsoleDocumentAdapter.documentAboutToBeChanged→StyledText.handleTextChanging→TextLayout.computeRuns→ native shaping.
-
-
QueueProcessingJobdrains all pending output (pendingPartitions.drainTo(...)) and processes it in one UI job, while holding thepartitionslock.- In the worst case, up to ~16 MB of pending text (the queue’s capacity) can be processed in one go.
- Each large
document.replaceon a big document forcesStyledTextto recompute layout, which scales poorly with document size, line length, and wrapping.
- If console output limiting is disabled (watermarks
-1, -1), the console document can grow without bound.- That makes each subsequent layout more expensive, especially with word wrap or complex fonts.
- Even when limit is enabled, the current implementation still applies all pending output to the document and then trims, so text that will be discarded still passes through layout.
-
helpProgress()can runprocessPendingPartitions()directly on whichever thread is callingstreamAppended(...).- If any code writes to the console from the UI thread (not the usual case, but possible),
helpProgress()can run the entireQueueProcessingJobsynchronously inside a UI event or paint, further increasing the chance of visible stalls.
- If any code writes to the console from the UI thread (not the usual case, but possible),
Net effect: under heavy or bursty console output, particularly with disabled or high watermarks and word wrapping, QueueProcessingJob can issue very large document.replace operations from the UI thread, forcing StyledText to do large-scale layout and text shaping. This can easily consume tens of seconds of CPU time, manifesting as the reported UI freeze.
4. Potential fixes in this code base
Below are concrete directions for fixes that can be implemented in this repository. They focus on limiting the amount of work done per UI pass and avoiding layout for text that will be discarded.
4.1 Limit work per QueueProcessingJob run
Problem:
-
processPendingPartitions()drains the entirependingPartitionsqueue and processes all output in onerunInUIThreadcall. - With high-volume output, this can mean processing many megabytes in a single UI job, blocking the UI for a long time.
Potential change:
- Introduce an upper bound on the amount of text processed in a single UI run, e.g.:
-
MAX_CHARS_PER_RUN(e.g. 256k or 512k characters), or -
MAX_PENDING_PER_RUN(limited number ofPendingPartitionentries).
-
- Modify
processPendingPartitions()to:- Accumulate
PendingPartitions frompendingPartitionsuntil the per-run limit is reached. - Leave remaining entries in the queue.
- After
applyStreamOutput(...)completes, reschedulequeueJobif the queue is still non-empty.
- Accumulate
Expected impact:
- Each
runInUIThreadexecution becomes bounded in time, preventing 10+ second single-pass stalls. - Console throughput remains high, but updates are amortized over multiple UI jobs, giving the event loop a chance to process other events between chunks.
- This is a local change in
IOConsolePartitioner.QueueProcessingJoband does not alter public API.
Notes:
- The existing comment about draining the whole buffer to “skip drawing text that exceeds the console buffer size” would need updating.
- Even with chunking,
checkBufferSize()can still be used to ensure trimming, but the layout cost will be distributed across multiple jobs instead of a single massive update.
- Even with chunking,
4.2 Avoid layout work for text that will be trimmed
Problem:
- When the console has a high-water mark configured and a large amount of new text arrives, we currently:
- Apply all text to the document via
applyStreamOutput(...)andapplyOutputToDocument(...). - Then run
checkBufferSize()andtrim(...)to enforce watermarks.
- Apply all text to the document via
- Text that is immediately trimmed still incurs the full cost of layout and partitioning.
Potential change:
- Before building the final
contentinapplyStreamOutput(...), compute how much of the pending text would actually be visible after trimming:- Use
document.getLength(),highWaterMark, andlowWaterMarkto determine the maximum number of characters worth appending. - Skip or partially skip older pending segments that are guaranteed to be trimmed away, updating
outputOffset/partitions as if the characters had been written, but without callingdocument.replacefor them.
- Use
- Only call
applyOutputToDocument(...)with the subset of text that will remain in the document after trimming.
Expected impact:
- Reduces the amount of text StyledText must lay out for long-running consoles that are already beyond their configured buffer size.
- Works especially well when debuggee output exceeds the configured high water mark by a large margin in short bursts.
Complexity considerations:
- Partition and
outputOffsetbookkeeping still need to reflect the full logical output, even for skipped regions. - This is more invasive than chunking, so it is a second-stage optimization after per-run limits.
4.3 Enforce safer defaults and bounds for console buffer size
Problem:
- If users disable
CONSOLE_LIMIT_CONSOLE_OUTPUTin debug preferences,setWaterMarks(-1, -1)disables trimming entirely. - A single console can then accumulate very large documents, making every layout operation expensive.
Potential change:
- In
ProcessConsole.init()andpropertyChange(...), clamp watermarks to reasonable maxima even when the preference suggests “unlimited”:- Example: if user disables the limit, internally use a large but finite default (e.g. 1–5 million characters) instead of
-1. - Alternatively, introduce a hard upper bound on highWaterMark (e.g.
Math.min(configuredHigh, MAX_SAFE_HIGH_WATER_MARK)).
- Example: if user disables the limit, internally use a large but finite default (e.g. 1–5 million characters) instead of
Expected impact:
- Prevents pathological console sizes that can lead to multi-second layout times, while still respecting the intention of “large” buffers.
- Requires careful communication or release notes, since it slightly changes the behavior of the “unlimited” setting.
4.4 Guard against synchronous processing from the UI thread
Problem:
-
helpProgress()callsprocessPendingPartitions()directly whenDisplay.getCurrent() != null, i.e. whenstreamAppended(...)is invoked on the UI thread.
Potential change:
- Change
helpProgress()so that it never runsprocessPendingPartitions()synchronously on the UI thread:- Always schedule
queueJobinstead (possibly withschedule(0)). - If necessary, keep a small timeout/back-pressure mechanism for non-UI threads only.
- Always schedule
Expected impact:
- Ensures that even if code writes to the console from the UI thread, it does not trigger an unbounded chunk of console processing in the middle of unrelated UI logic.
5. Summary
- The freeze reported in
workspace.logis caused by heavy SWTTextLayoutwork on the main UI thread during console output updates. - The concrete code path runs through
IOConsolePartitioner.QueueProcessingJob, which currently:- Drains up to ~16 MB of pending output in a single UI job,
- Performs all parsing and partition updates under a lock in the UI thread, and
- Applies large
document.replaceoperations that trigger expensiveStyledTextlayout viaConsoleDocumentAdapter.
- Under high or bursty output, especially with large/unchecked console buffers and word wrapping, this can lead to multi-second UI stalls even though the thread is not blocked on locks.
- The most promising fixes within this repository are:
- Limiting per-run work in
QueueProcessingJob(chunking pending output), - Avoiding layout for text that will immediately be trimmed,
- Enforcing safer bounds on console buffer size, and
- Avoiding direct
processPendingPartitions()calls from the UI thread.
- Limiting per-run work in
These changes keep console behavior functionally the same while significantly reducing the risk of long UI freezes caused by console output processing.
Have you enabled "line wrapping" in the Console? That may require extra CPU cycles...
Yes it was enabled. Console buffer size is already set to only 20.000 chars.
I'll try to disable it but it should not freeze the whole UI for minutes. I waited for 5 minutes and killed the process.
Do you have any monitor scaling (i.e., zoom != 100%) enabled for either the monitor your application window is placed on or for your primary monitor?
I have to admit that I don't know well the involved code, but I have seen how sensitive the TextLayout is to not properly fitting calculated sizes between itself and the StyledText, which may cause errors or long running calculations. There are many pixel/point conversions used in TextLayout, so it could be that some of the calculated values' rounding is unfortunately off at specific zooms or with specific configurations (such as the mentioned line wrapping, which probably also operates on pixel/point converted values).
No I am not using any scaling.
Unfortunately I couldn't determined a specific usage pattern that results in the freeze. It just randomly freezes.
Thank you! Still good to know, as we can exclude that category of potential causes then.