fix: guard terminal resize against disposal to prevent xterm dimensions error (fixes #316419)#316424
Open
vs-code-engineering[bot] wants to merge 1 commit into
Open
Conversation
…ns error (fixes #316419) During _onProcessExit → dispose(), the _onDisposed event fires before super.dispose() is called, so isDisposed is still false. Event listeners triggered during _onDisposed can reach setVisible → _resize → _updatePtyDimensions, which accesses xterm's dimensions getter. The getter throws because xterm's internal renderer is in a bad state during the disposal process. Add a _isDisposing flag set at the start of dispose() and check it in _resize() to prevent resize operations during the entire disposal process, not just after it completes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔧 Error Fix
Summary
Error:
Cannot read properties of undefined (reading 'dimensions')— aTypeErrorthrown by xterm.js'sTerminal.dimensionsgetter when its internalRenderService._renderer.valueisundefinedpost-disposal.Impact: 48.6M hits across 4.9M users. Affects all platforms (Linux, Mac, Windows). Bucket
1e83a096-ed50-2ba1-2dd8-46381020bd02.Root cause: During
TerminalInstance.dispose(), the_onDisposedevent fires at line 1327 beforesuper.dispose()is called at line 1345. This meansisDisposedis stillfalseduring the event chain. Listeners triggered by_onDisposedcan dispose timers/schedulers whose callbacks fire configuration change events. These config changes reachsetVisible()on the disposing terminal, which calls_resize()→ debouncer →_resizeBothCallback→_updatePtyDimensions(). The existingisDisposedguards in the callback and_updatePtyDimensionspass (returningfalse), and the xtermdimensionsgetter throws because the renderer is in a bad state during the disposal process.Fixes #316419
Recommended reviewer:
@TyriarCulprit Commit
This is a long-standing issue (bucket first seen at v1.109.5, March 2026) exacerbated by the xterm.js beta.213 bump (
644c7175by@bryanchen-d). The prior fix attempt addedisDisposedguards and a try/catch (644c7175), then the try/catch was removed (5e647b29) on the assumption thatisDisposedguards were sufficient. They are not sufficient for the_onDisposed.fire()path whereisDisposedis stillfalse.Code Flow
sequenceDiagram participant PE as _onProcessExit participant D as dispose() participant EV as _onDisposed listeners participant CC as Config Change participant SV as setVisible participant R as _resize participant DB as ResizeDebouncer participant UP as _updatePtyDimensions participant XT as xterm.dimensions getter PE->>D: dispose(TerminalExitReason.Process) Note over D: isDisposed = false (super.dispose() not yet called) D->>EV: _onDisposed.fire(this) EV->>CC: listener disposes timer, timer callback fires CC->>SV: config change triggers setVisible(true) SV->>R: _resize() R->>DB: resize(cols, rows, immediate) DB->>UP: _resizeBothCallback, _updatePtyDimensions(xterm.raw) UP->>XT: rawXterm.dimensions Note over XT: renderer undefined, TypeErrorAffected Files
src/vs/workbench/contrib/terminal/browser/terminalInstance.tsHow the Fix Works
Chosen approach (
terminalInstance.ts): Added a_isDisposingflag that is set totrueat the start ofdispose()(before_onDisposed.fire()) and checked in_resize()alongsideisDisposed. This guards against resize operations during the entire disposal process, not just aftersuper.dispose()completes. The fix is at the data producer level — preventing the resize call from being made when the terminal is mid-disposal, rather than catching the error at the crash site (the xterm getter).Alternatives considered:
dimensionsaccess: wraps the crash site, hides the bug.isDisposedin_resize: insufficient becauseisDisposedisfalseduring_onDisposed.fire().super.dispose()before_onDisposed.fire(): breaks contribution addon cleanup.Recommended Owner
@Tyriar— primary owner of the terminal component.@bryanchen-dpreviously worked on this exact bucket.