Skip to content

Fix captureScreen hang when server responds with only pseudo-encodings#315

Merged
sibson merged 1 commit intosibson:mainfrom
HZNAN:fix/commitUpdate-pseudo-encoding-hang
Apr 11, 2026
Merged

Fix captureScreen hang when server responds with only pseudo-encodings#315
sibson merged 1 commit intosibson:mainfrom
HZNAN:fix/commitUpdate-pseudo-encoding-hang

Conversation

@HZNAN
Copy link
Copy Markdown
Contributor

@HZNAN HZNAN commented Apr 8, 2026

Problem

captureScreen (and the CLI capture command) hangs indefinitely when the VNC server responds to a FramebufferUpdateRequest with only pseudo-encoding rectangles and no actual pixel data.
This has been reported in #267 and affects multiple VNC servers including TigerVNC and WayVNC.

Reproduction

$ vncdo -s ::5900 -p capture screenshot.png

Debug log shows the server returns only pseudo-encodings:
DEBUG:vncdotool.client:captureScreen screenshot.png INFO:twisted:x=0 y=0 w=0 h=0 <Encoding.PSEUDO_QEMU_EXTENDED_KEY_EVENT: -258> INFO:twisted:x=0 y=0 w=0 h=0 <Encoding.PSEUDO_LAST_RECT: -224>

hangs forever here

Root Cause

In rfb.py, _doConnection() only calls commitUpdate() when rectanglePos is non-empty:

if self.rectanglePos:
    self.commitUpdate(self.rectanglePos)
Pseudo-encoding handlers (e.g. PSEUDO_QEMU_EXTENDED_KEY_EVENT) append to rectanglePos then immediately delete their entry. When a FramebufferUpdate contains only pseudo-encodings, rectanglePos ends up emptycommitUpdate() is never calledthe Deferred from captureScreen is never resolvedinfinite hang.

Fix
Always call commitUpdate() when all rectangles in a FramebufferUpdate have been processed, regardless of whether rectanglePos is empty. This ensures the Deferred is always resolved.

Test Environment
vncdotool main branch
VNC Server: TigerVNC 1.13 (Windows)
Client: Python 3.11 (Linux, Docker container)

When a VNC server (e.g. TigerVNC, WayVNC) responds to a
FramebufferUpdateRequest with only pseudo-encoding rectangles (such as
PSEUDO_QEMU_EXTENDED_KEY_EVENT and PSEUDO_LAST_RECT), the capture
command hangs indefinitely.

Root cause: In _doConnection(), commitUpdate() is only called when
rectanglePos is non-empty. However, pseudo-encoding handlers remove
their entries from rectanglePos, so when a FramebufferUpdate contains
only pseudo-encodings, rectanglePos ends up empty and commitUpdate()
is never called. This leaves the Deferred unresolved forever.

Fix: Always call commitUpdate() when all rectangles in a
FramebufferUpdate have been processed, regardless of whether
rectanglePos is empty.

Fixes sibson#267

Made-with: Cursor
@HZNAN HZNAN force-pushed the fix/commitUpdate-pseudo-encoding-hang branch from c6f406c to 5848414 Compare April 8, 2026 13:55
@HZNAN HZNAN closed this Apr 8, 2026
@HZNAN HZNAN reopened this Apr 8, 2026
@sibson
Copy link
Copy Markdown
Owner

sibson commented Apr 11, 2026

thanks, ✨ 🍰 ✨

@sibson sibson merged commit 8bd7d58 into sibson:main Apr 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants