Skip to content

Callback dispatcher bypasses crosscall2 — crashes on C-created threads #16

@kolkov

Description

@kolkov

Summary

The callback dispatcher (both AMD64 and ARM64) calls callbackWrap directly via CALL/BL, bypassing the crosscall2 → runtime·load_g → runtime·cgocallback chain that purego and Go runtime use for proper C-to-Go transitions.

This works correctly when callbacks arrive on Go-managed threads (the primary WebGPU use case), but will crash if a C library invokes the callback from its own internally-created thread (G = nil).

Current behavior

  • Callbacks on Go threads: works (goroutine pointer already loaded)
  • Callbacks on C threads: crash (SIGSEGV, nil goroutine pointer)

Expected behavior

Callbacks should work regardless of which thread invokes them, matching purego's behavior.

Potential impact without crosscall2

Scenario Risk Severity
Callback on Go thread Minimal — G already loaded Low
Callback on C thread (e.g. wgpu-native internal) Crash — G = nil Critical
GC during long callback Incorrect stack scanning Medium
Preemption signal during callback Undefined behavior on C stack Medium

Solution

Replace direct BL ·callbackWrap / CALL ·callbackWrap with BL crosscall2 / CALL crosscall2 in both dispatchers, following the purego pattern:

// ARM64 (purego reference):
MOVD ·callbackWrap_call(SB), R0   // fn (ABIInternal closure)
MOVD R13, R1                       // frame (&callbackArgs)
MOVD $0, R3                        // ctxt = 0
BL   crosscall2(SB)

Files to change

  • ffi/callback_amd64.s — AMD64 dispatcher
  • ffi/callback_arm64.s — ARM64 dispatcher
  • ffi/callback.go — add callbackWrap_call closure (AMD64)
  • ffi/callback_arm64.go — add callbackWrap_call closure (ARM64)

Context

Discovered during ARM64 trampoline fix (BL→MOVD+B, see #15). The direct call approach was inherited from the initial implementation and is documented in TASK-012-crosscall2-integration.md.

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions