Skip to content

[Based on #2090] ssa,runtime: tighten recover to direct deferred calls#2033

Open
cpunion wants to merge 2 commits into
xgo-dev:mainfrom
cpunion:codex/stage5-recover-defer
Open

[Based on #2090] ssa,runtime: tighten recover to direct deferred calls#2033
cpunion wants to merge 2 commits into
xgo-dev:mainfrom
cpunion:codex/stage5-recover-defer

Conversation

@cpunion

@cpunion cpunion commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Depends on #2090

Problem

Go permits recover() only when it is called directly by the deferred function currently handling the panic. An indirect helper, nested closure, or recursive sub-call must receive nil. The prior runtime could not reliably distinguish those calls.

Implementation

  • associate each panic node with its owning Defer frame and check that ownership in Recover;
  • extend runtime: store goroutine state behind pthread-key getg #2090's pthread-key g with panic, recover-frame, Goexit, and defer ownership;
  • preserve closure and method-value wrapper transparency with recover-frame aliases;
  • keep the existing unrecovered PanicTraceback hook and report the panic node's argument;
  • mark may-recover LLVM functions with a module-local string attribute instead of a process-global map.

LLVM value handles can be reused after module disposal, so a global recover-classification cache could leak stale state into a later package. This PR adds no pthread key and no second per-goroutine store.

The independent diff is +628/-155 across 16 files.

Conformance

Removed xfails for:

  • fixedbugs/issue4066.go
  • fixedbugs/issue73916.go
  • fixedbugs/issue73916b.go

Validation

  • macOS arm64, Go 1.26.5: affected SSA/compiler tests and real-LLGo recover regressions pass.
  • Ubuntu arm64, Go 1.26.5, LLVM 19.1.7: the same focused recover suite passes in an 8 GiB, 2 CPU, no-swap container.
  • MarkMayRecover and its query path are covered, including repeated package compilation.
  • No existing test is disabled or ignored.

This supersedes the remaining recover-ownership portion of #1918.

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from e617ca2 to 174dfa3 Compare July 6, 2026 13:58
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 6, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 174dfa3 to f9fabc8 Compare July 8, 2026 05:28
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 8, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from f9fabc8 to f72a070 Compare July 8, 2026 07:04
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 8, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from f72a070 to efa8f54 Compare July 8, 2026 11:17
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 8, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from efa8f54 to d08e486 Compare July 9, 2026 05:31
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 9, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion cpunion added go-test-compat Go standard-library and GOROOT test compatibility bug Something isn't working bugfix Fixes an existing bug or regression go1.26 Go 1.26 compatibility and support and removed bug Something isn't working labels Jul 16, 2026
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from d08e486 to bb7c5bf Compare July 16, 2026 04:36
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 16, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion cpunion changed the title ssa,runtime: tighten recover to direct deferred calls (Defer-node model) [Based on #2090] ssa,runtime: tighten recover to direct deferred calls Jul 16, 2026
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from bb7c5bf to 82202d4 Compare July 17, 2026 11:47
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 17, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 82202d4 to 5bd32a8 Compare July 18, 2026 10:18
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 5bd32a8 to 9e923c8 Compare July 18, 2026 23:30
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 18, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 9e923c8 to eacab1b Compare July 19, 2026 00:14
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 19, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from eacab1b to 56805f4 Compare July 20, 2026 06:10
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 20, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 56805f4 to 3586239 Compare July 23, 2026 09:31
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 23, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 3586239 to 06d1e2e Compare July 23, 2026 10:50
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 23, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
cpunion added 2 commits July 24, 2026 11:23
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were
the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain):

- recover() only succeeds when called directly by a deferred function
  (gc semantics): the panic node records the owning Defer frame at
  rethrow (panicKey/panicNode + GoDeferData), and Recover checks the
  caller is that frame's direct deferred call. Closure wraps carry
  StartRecoverFrameAlias/EndRecoverFrame so method-value and closure
  adapters stay transparent to the ownership check.
- Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path.
- xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in
  ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover
  semantics), validated on darwin/arm64 go1.26.

Supersedes xgo-dev#1918.
cpunion added a commit to cpunion/llgo that referenced this pull request Jul 24, 2026
…s; recover conformance

Re-expresses the surviving value of xgo-dev#1882 on top of xgo-dev#2033 (its remaining
~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded):

- Failed (non-comma-ok) type assertions panic with a real
  *runtime.TypeAssertionError built at runtime (TypeAssertError +
  missing-method lookup from abi tables) instead of a plain errorString;
  the recovered value implements runtime.Error, matching gc. The
  source-interface abi type is deliberately not materialized at the
  assert site: doing so can reference another package's private
  local-generic symbols (undefined at link); the message's interface
  name is the documented mdempsky/16 residual.
- SIGBUS joins SIGSEGV in the fault-to-panic signal path (per-OS signal
  constants; darwin/linux).
- goroot xfails retired, validated darwin go1.26 + go1.24: recover2.go,
  recover4.go, zerodivide.go, fixedbugs/issue73917.go, issue73920.go.
- recover1.go stays xfailed with an updated reason (recursive-panic
  sub-call recover masking - Defer-node model follow-up); three ported
  tests covering the same class are t.Skip'ed with that pointer.
- Golden CHECK updates: assert-failure sites now emit
  TypeAssertError+Panic; constants renumbered from actual IR.

Supersedes xgo-dev#1882.
@cpunion
cpunion force-pushed the codex/stage5-recover-defer branch from 06d1e2e to a869220 Compare July 24, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fixes an existing bug or regression go1.26 Go 1.26 compatibility and support go-test-compat Go standard-library and GOROOT test compatibility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant