Skip to content

fix(code): unblock main thread by decompressing skills zips off-thread#2242

Merged
k11kirky merged 1 commit into
mainfrom
posthog-code/fix-unzip-blocking-main-thread
May 20, 2026
Merged

fix(code): unblock main thread by decompressing skills zips off-thread#2242
k11kirky merged 1 commit into
mainfrom
posthog-code/fix-unzip-blocking-main-thread

Conversation

@k11kirky
Copy link
Copy Markdown
Contributor

Summary

  • PosthogPluginService.updateSkills() runs during startup and calls fflate.unzipSync on the downloaded skills + context-mill archives. Pure-JS sync decompression on the Electron main thread pegged CrBrowserMain for tens of seconds on launch, surfacing as an app-hang for users on v0.52.0 (Unresponsive for 81 seconds before sampling in the crash log).
  • Swap to fflate's async unzip via a small unzipAsync promisify helper in extract-zip.ts. Used by both extractZip and the inner omnibus-zip path in update-skills-saga.ts. Async unzip yields the event loop so the main thread stays responsive during extraction.
  • Build-time scripts (vite.main.config.mts, scripts/pull-skills.mjs) keep unzipSync — they don't run in the Electron app.

Root cause (from the crash log)

Main thread stuck at node::fs::FileHandle::CloseReq::Resolve → V8 → JIT'd JS for all 41/41 samples — the promise continuation right after await readFile(zipPath) resolves, which is exactly where unzipSync ran. All 4 libuv-worker threads parked in uv_cond_wait, confirming the hang was pure CPU on the main thread, not I/O. 1.3 GB footprint matched the fully-materialized decompressed zip held in memory.

Test plan

  • pnpm --filter code typecheck clean
  • pnpm --filter code test — all 1348 tests pass (one mock updated from unzipSync to async unzip)
  • Manual: launch packaged build on a clean profile and confirm the app reaches the renderer without hanging while skills download

Generated-By: PostHog Code
Task-Id: 0270afde-6140-4867-bd57-52ae8a767a4d

PosthogPluginService runs updateSkills() during app startup, which calls
fflate.unzipSync on the downloaded skills + context-mill archives. Pure-JS
sync decompression on the Electron main thread pegged CrBrowserMain for tens
of seconds on launch, surfacing as an app-hang for users on v0.52.0.

Swap to fflate's async unzip via a small unzipAsync promisify helper in
extract-zip.ts, used by both extractZip and the inner omnibus-zip path in
update-skills-saga.ts. Async unzip yields the event loop so the main thread
stays responsive during extraction.

Build-time scripts (vite.main.config.mts, scripts/pull-skills.mjs) keep
unzipSync — they don't run in the Electron app.

Generated-By: PostHog Code
Task-Id: 0270afde-6140-4867-bd57-52ae8a767a4d
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 20, 2026

Reviews (1): Last reviewed commit: "fix(code): unblock main thread by decomp..." | Re-trigger Greptile

Copy link
Copy Markdown
Member

@andrewm4894 andrewm4894 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was just looking into this too when doing local dev for some inbox stuff

@k11kirky k11kirky merged commit 3d1c338 into main May 20, 2026
15 checks passed
@k11kirky k11kirky deleted the posthog-code/fix-unzip-blocking-main-thread branch May 20, 2026 14:02
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