mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[GH-ISSUE #4921] [Bug] Hopper (Linux): session teardown leaves a stale /tmp/.X<n>-lock; accumulated locks can make startup fail with address_collision #3054
Closed
opened 2026-10-31 00:35:35 +00:00 by bsakaguchi
·
3 comments
No Branch/Tag specified
main
codex/procedure-reference-stacked
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
morluto/rea#3054
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Abel-I-Akhigbe on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4921
Before submitting
Area
Native analysis or decompilation
Observed behavior
On Linux with the Hopper demo provider (private Xvfb,
user-mount-namespacestrategy), Hopper sessions run over MCP leave/tmp/.X<n>-lockfiles behind after they end. Each file is owned by the invoking user and records a PID that is no longer running. No Xvfb process remains. Teardown looked clean wherever we recorded it:close_binaryreturned without error ({"result":null}).owned-shutdownwith statusverified-cleanup.Counts were taken per batch. Before each batch, all lock files had been removed. After each batch, the number of new lock files equalled the number of Hopper sessions in it:
close_binary, 1 × a session ended by closing the client's stdin withoutclose_binary.close_binary, 1 × stdin EOF.Two of the seven locks were also traced to their sessions. In each batch, the
close_binarysession's process tree was recorded while it was open, and it included an Xvfb PID. One of the batch's leftover locks names that PID: 1198147 →/tmp/.X535-lockin batch A, and 1353852 →/tmp/.X626-lockin batch B. The other five locks were counted per batch only.Before these batches, 8 lock files with dead PIDs were found. Their modification times were 15:29–18:40 the same day, and they were not mapped to specific sessions.
Control: running the helper
scripts/hopper-demo-x11.pydirectly in--probemode, with the sameuser-mount-namespacestrategy, left 0 new lock files.Reproduction
Linux x86_64 with the Hopper 6.4.2 demo, Xvfb and xauth installed. REA selected the
user-mount-namespacestrategy; here/tmp/.X11-unixis read-only (WSLg).Build the fixture with
gcc -g -O0 -fno-pie -no-pie probe.c -o probe:Run
ls /tmp/.X*-lockand note the result.Start
rea mcpand send thesetools/callrequests in order:open_binary{"path": "<abs path>/probe", "provider_id": "hopper"}procedure_pseudo_code{"procedure": "rea_provider_probe"}close_binary{}To tie the lock to this session, run
pgrep -a Xvfbbeforeclose_binaryand note the PID.Run
ls /tmp/.X*-lockagain and compare. Frequency in our runs: 7 sessions produced 7 new locks across 2 batches; 2 locks were individually matched to their sessions by Xvfb PID, while the other 5 were counted only at batch level (see Observed behavior). For a new file,catit to get its PID:/proc/<pid>does not exist, andpgrep Xvfbfinds nothing.Both batches also included a session ended by closing the client's stdin instead of calling
close_binary, and the counts still matched.Expected behavior
When a Hopper session ends, its Xvfb lock file is removed. Reference: the helper's own shutdown,
stop_process, sends Xvfb SIGTERM and waits. The--probecontrol ends through that path, per the source, and left no lock (observed).Proposed fallback, not a documented contract: a lock whose PID no longer exists should not stop a later session from using that display number.
Impact and scope
Reliability, not confidentiality: the lock files contain only a PID.
rea_provider_probe, and their server exited 0./tmpis cleaned (distribution policy or a reboot).Potential impact, derived from the source and not observed (details under Analysis): each leftover lock blocks one of the 900 display numbers Hopper picks from. Startup gives up after 3 blocked picks, so it fails more often as locks accumulate. Under the stated assumptions, that is about 3.7% at 300 locks and 30% at 600. Long-lived hosts that run many Hopper sessions would degrade gradually.
REA version
6.5.0 (installed); source analysis at main
f4322b15; the cited code is unchanged at maind0253c99(2026-10-17T23:06Z)Runtime and platform
Node.js 26.12.0 (also seen on 26.5.1); Ubuntu 24.04 on WSL2, kernel 6.18, x86_64; Hopper 6.4.2 demo; Xvfb 2:21.1.12-1ubuntu1.5 and -1ubuntu1.8
Target and artifact context
Small x86_64 ELF built from the two-function fixture under Reproduction; only this fixture was tested
Interface
MCP
Earliest failure stage
Cleanup, cancellation, or lifecycle
Relevant output or evidence
Command or MCP request actually run:
rea mcp, with the threetools/callrequests under Reproduction. Batch B had 3 sessions: one native verification flow, one ended withclose_binary, and one ended by closing stdin. No lock files existed beforehand.Relevant result, error, or artifact:
close_binarysession's process tree, recorded by an audit process inspector while the session was open. It supports the PID match for/tmp/.X626-lock(excerpt):/proc/<pid>, and removes the lock only if the PID is dead. It supports "3 sessions → 3 stale locks":verified-cleanup":--probe, in the sameuser-mount-namespacestrategy, left 0 new lock files.For source-only findings, link the file/revision and relevant code: the commit-pinned links under Analysis or suspected cause. They point to
f4322b15. The cited code is unchanged atd0253c99:BridgeLauncher.ts,ProcessOwnership.tsandhopper-demo-x11.pyare byte-identical, and inProviderProcess.tsonly the line numbers of the cited code moved (+26). See the re-check below.Missing evidence or remaining uncertainty:
mainbuild; the source was only compared.Typed outcome or recovery expected
verified-cleanupshould mean that nothing the session created is left. The session's display lock should be gone before teardown reportsverified-cleanup. If it is not, teardown should report the leftover lock as a cleanup residual. A later Hopperopen_binaryshould not fail withaddress_collisionbecause of locks whose PID no longer exists.Analysis or suspected cause
Source-derived; no signal trace was captured. Links and line numbers are pinned to main
f4322b15; the 6.5.0 package has the same code.src/hopper/BridgeLauncher.ts:306-314: the Hopper launch setscleanup = () => cleanupOwnedProcessGroup(started.ownership).src/process/ProviderProcess.ts:581-605: whenlaunch.cleanupis set, stopping runs that callback. The SIGTERM → grace → SIGKILL path at lines 610-617 is not used.src/process/ProcessOwnership.ts:276:cleanupOwnedProcessGroupsendsSIGKILLto each owned process group, with no SIGTERM first.scripts/hopper-demo-x11.pyinstalls no signal handler. It starts Xvfb with a plainsubprocess.Popen, with no new session or process group. Xvfb is stopped only bystop_process(lines 462-470), which sends SIGTERM and then waits.stop_processis called from the helper's own exit paths:run_launch'sfinally(lines 807-812) andrun_probe(lines 647-655). A process-group SIGKILL never runs those paths.Suspected cause: teardown SIGKILLs the helper's process group, Xvfb included. Xvfb never runs its orderly shutdown, so its lock file stays. In the
--probecontrol, the helper stops Xvfb with SIGTERM, and no lock is left.Display selection and the failure estimate, also source-derived:
scripts/hopper-demo-x11.py:576-644holdsstart_xvfb, which is used when no display number is given. It tries at most 3 random display numbers in 100–999 (100 + secrets.randbelow(900), line 583)./tmp/.X<n>-lockor/tmp/.X11-unix/X<n>as a collision (lines 585-595).address_collisionalso uses up a try (lines 637-639). After 3 tries it raisesaddress_collision(line 640).Assume L distinct blocked display numbers in 100–999, 3 independent uniform picks with replacement, and no other failures or concurrent sessions. Startup then fails with probability (L/900)³:
Re-check at main
7e4eed9d(2026-10-17T22:33Z), 53 commits later:BridgeLauncher.ts,ProcessOwnership.tsandhopper-demo-x11.pyare byte-identical tof4322b15.ProviderProcess.ts, the cleanup branch and the SIGTERM path are textually identical but moved to lines 607-631 and 636-643. The other changes in that file concern output-close accounting.d0253c99(2026-10-17T23:06Z).Possible fixes (untested suggestions):
stop_processon Xvfb./tmp/.X<n>-lockfor the display the session owned, but only if the lock still names that session's Xvfb PID.start_xvfb, treat a lock owned by the current user whose recorded PID no longer exists as reclaimable, not as a collision.Additional context
Related but distinct: #3985 (a timed-out probe survives close), #4227 (lifecycle contract audit), #3436 (xauth argv).
No duplicate was found in the recorded searches (
gh search issues, all states, on 2026-10-17 and again at 2026-10-17T22:49Z). Queries:"X lock",Xvfb lock,stale lock,address_collision,display collision,X11 lock,hopper Xvfb,hopper cleanup SIGKILL,.X11-unix,Xvfb OR X11 OR lock OR display in:title,body.Workaround: remove stale locks that you own and whose PID is not running. Checking and deleting are separate steps, so an X server starting on the same display in between could lose its new lock. Run this only while no Hopper session or other X server is starting.
This snippet was tested on fake lock files in a private scratch directory, not on a live
/tmp.Under dash, 9 lock files:
%10dformat, and unpadded: removed;abc,-5,123 456): kept;Under bash, 3 lock files:
abc: kept.Also under bash, a directory with no lock files: nothing removed, exit status 0.
A lock owned by another user was not tested.
Proposed regression test: run one Hopper session through MCP and end it with
close_binary, then again by closing stdin. In each case, assert that no/tmp/.X<n>-lockremains for the display the session used.Publication re-check (2026-10-17T23:49:59+00:00): the four source files above and the bug-report form are unchanged between
d0253c99and upstream maind205c528. Fresh all-state issue searches for Xvfb/lock, stale/lock/Hopper,address_collision, X11/lock, and session-teardown/Hopper found no duplicate. This was a source and issue-search check; no newer build was executed.@XinwangTao commented on GitHub (Oct 18, 2026):
Thanks for the detailed report — the per-session lock matching (PID → /tmp/.X-lock) makes the root cause fairly clear: the X server lock file is left behind even though the Xvfb process itself is gone and teardown reports verified-cleanup. Since the lock records a dead PID, the cleanup verification is probably only checking the process tree, not the lock artifact itself.
Suggestions:
The proposed regression test (no /tmp/.X-lock remains after close_binary and after stdin EOF) looks reasonable — would also recommend asserting the lock count is unchanged after a full batch, not just a single session.
@matbrgz commented on GitHub (Oct 19, 2026):
Cross-referencing with sibling Hopper session teardown reports in Cluster AB: #4226 (
[Bug] Hopper pre-handshake startup failure causes repeated cleanup errors while session reports idle) and recent fix #5189. Both isolate virtual X11 server lifecycle management on Linux where orphaned lock files (/tmp/.X<n>-lock) persist across sessions and causeaddress_collisionon subsequent startups.Consolidated under Cluster AB (Hopper Linux Virtual X11 Display & Stale Lock Cleanup Failures) in tracker #4330.
@XinwangTao commented on GitHub (Oct 20, 2026):
Agree with the consolidation — #4226 and #5189 share the same Linux X11 lifecycle root, and grouping them under Cluster AB in #4330 keeps the stale-lock pattern visible. The #4966 fix (orderly demo-helper shutdown so the X lock is removed) covers the teardown half of the report; the defense-in-depth half from my earlier comment — startup reclaiming locks whose recorded PID is dead — would still be worth a follow-up so a single crashed session can't wedge later startups.