Frozen on another monitor

Published by Gonzalo Tudela Chavero

The bug

Dragging the browser window from one monitor to another froze this site: no redraw, no keyboard, no tabs. Only on screens with a different scaling (100% to 150%, for example), and only sometimes.

Reproducing it

Headless Chrome can change the device pixel ratio of a running page through the DevTools protocol, so the bug could be triggered on demand. The console showed a single line: RuntimeError: unreachable. With panic = "abort" a Rust panic in WebAssembly ends up as exactly that, with no message, and the whole module stops: the animation loop dies with it.

A one-line panic hook that writes the message to the console turned the mystery into a location: tachyonfx/src/fx/glitch.rs:130, an unwrap() on a cell that did not exist.

The cause

The terminal grid is sized from the canvas in physical pixels. When the pixel ratio changes, the WebGL backend recalculates the grid on its own, in the middle of a frame. Visual effects, like the glitch that fires every 10-25 seconds, keep the area they were created with. A glitch created on the old grid then tried to write a cell outside the new one.

The fix

Tested by switching the ratio between 1, 1.25, 1.5 and 2, with a glitch running at the same time.