Export pgoutput.so imports from the main wasm module to enable logical replication slots#79
Open
riderx wants to merge 1 commit into
Open
Conversation
pgoutput.so is loaded at runtime as an emscripten side module, but unlike
pgxs-built extensions its undefined symbols were never collected into the
exported-functions list. With -sMAIN_MODULE=2, symbols used only by
pgoutput (defGetStreamingMode, logicalrep_write_*, publication lookup
functions, etc. - 46 in total) were dead-code-eliminated from the main
module, so any logical decoding session using pgoutput crashed at the
output plugin startup callback with a call to an undefined table entry.
Generate a pgoutput.imports file at install time, mirroring the pgxs.mk
recipe, so the pglite-exported-functions target keeps those symbols alive.
This makes logical replication slots usable in PGlite:
SELECT pg_create_logical_replication_slot('slot', 'pgoutput');
SELECT * FROM pg_logical_slot_get_binary_changes('slot', NULL, NULL,
'proto_version', '1', 'publication_names', 'pub');
Fixes electric-sql/pglite#880
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
riderx
pushed a commit
to riderx/pglite
that referenced
this pull request
Jul 7, 2026
Points at the head of electric-sql/postgres-pglite#79 (served by the upstream repo via refs/pull/79/head, so submodule checkout by SHA works). Should be updated to the merge commit once that PR lands. Co-Authored-By: Claude Fable 5 <noreply@anthropic.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.
Problem
Logical replication slots don't work in PGlite (electric-sql/pglite#880). Even with
wal_level=logical, consuming a slot crashes the session:Root cause
pgoutput.sois loaded at runtime as an emscripten side module, but unlike pgxs-built extensions (which generate a.importsfile at install time that feeds-sEXPORTED_FUNCTIONSvia thepglite-exported-functionstarget), it is linked fromsrc/backend/replication/pgoutputviaMakefile.shlib, so its imports were never collected.With
-sMAIN_MODULE=2, every symbol used only by pgoutput gets dead-code-eliminated from the main module — 46 functions in the current build, includingdefGetStreamingMode, alllogicalrep_write_*,GetRelationPublications,CacheRegisterRelSyncCallback, etc. (verified by diffingWebAssembly.Module.imports(pgoutput.so)againstWebAssembly.Module.exports(pglite.wasm);GOT.memresolves fully, only function imports are missing).At runtime the first missing call happens inside pgoutput's startup callback, throws
TypeError: r is not a functionfrom aninvoke_*trampoline, and the JS side swallows it, leaving the backend permanently corrupted.Fix
Generate
pgoutput.importsat install time, using the samellvm-nmrecipe aspgxs.mk, so the existingpglite-exported-functionstarget picks it up and the symbols survive DCE.After rebuilding, all 46 previously-missing imports are exported from the main module and logical decoding with pgoutput works end-to-end (create/list/drop slots, peek/get binary changes, slot persistence across dump/load). Tests exercising this live in the companion PR to electric-sql/pglite, together with defaulting
wal_level=logicaland no longer swallowing unexpected WASM exceptions.Fixes electric-sql/pglite#880
🤖 Generated with Claude Code