Skip to content

cuda.bindings: pass host functions to cuLaunchHostFunc and cudaLaunchHostFunc unchanged - #3061

Open
Andy-Jost wants to merge 4 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/fix-790-host-func-trampoline
Open

Andy-Jost wants to merge 4 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/fix-790-host-func-trampoline

Conversation

@Andy-Jost

Copy link
Copy Markdown
Contributor

Summary

driver.cuLaunchHostFunc and runtime.cudaLaunchHostFunc routed the host function through an internal trampoline that freed its (fn, userData) record after the first call. A host function captured into a CUDA graph is called again on every launch of that graph, so the second launch used freed memory and crashed (#790). The wrappers now pass fn and userData to CUDA unchanged, as the _v2 variants already do.

Changes

  • cuda/bindings/driver.pyx, cuda/bindings/runtime.pyx: remove the cuHostCallbackWrapper and cudaStreamRtHostCallbackWrapper trampolines and their records; the two wrappers call CUDA with the caller's function pointer and user data. The generated-file seals are updated. The delta equals the output of the cybind generator with the matching fix (cybind MR !587), applied to the current bindings; the generator change reaches the public bindings through the regular regeneration.
  • tests/test_cuda.py, tests/test_cudart.py: capture a host function into a graph and launch it five times through the driver API and through the runtime API; the function must run once per launch. Both tests crash on the second launch without the fix.
  • 13.5.0 release note.

Related Work

Fixes #790. The generator side is cybind MR !587; review there asked for this PR to carry the output and a regression test that runs real code.

🤖 Generated with Claude Code

Andy-Jost and others added 2 commits October 9, 2026 08:00
…HostFunc unchanged

The two wrappers routed the call through an internal trampoline that
freed its (fn, userData) record after the first call. A host function
captured into a CUDA graph is called again on every launch of that
graph, so the second launch used freed memory and crashed. The wrappers
now pass fn and userData to the driver unchanged, as the _v2 variants
already do.

The bindings change equals the output of the cybind generator with the
matching fix. Two tests capture a host function into a graph and launch
it repeatedly, through the driver and the runtime API.

Fixes NVIDIA#790

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Andy-Jost Andy-Jost added bug Something isn't working P0 High priority - Must do! cuda.bindings Everything related to the cuda.bindings module labels Oct 9, 2026
@Andy-Jost Andy-Jost self-assigned this Oct 9, 2026
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/cuda-python/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 8b554a4d-c8fe-4dc9-bd05-714cd8169942
📥 Commits

Reviewing files that changed from the base of the PR and between 7a21ea4 and 9d5441d.

📒 Files selected for processing: 4
  • cuda_bindings/docs/source/overview.rst
  • cuda_bindings/docs/source/release/13.5.0-notes.rst
  • cuda_bindings/tests/test_cuda.py
  • cuda_bindings/tests/test_cudart.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Fixed host callbacks captured in CUDA graphs so they can run on repeated graph launches.
    • Host callbacks and their user data are passed directly to CUDA through both driver and runtime APIs.
  • Documentation
    • Clarified that callbacks and user data must remain available until pending launches finish; for graph captures, retain them until the graph and its executables are destroyed.
  • Tests
    • Added coverage verifying callbacks run once per launch across repeated graph replays.

The driver and runtime host-function bindings now pass callbacks and user data directly to CUDA. Tests capture callbacks in CUDA graphs and verify five launches each. Documentation describes callback and user-data lifetime requirements.

Changes: Host Function Graph Replay

Layer / File(s) Summary
Direct callback forwarding
cuda_bindings/cuda/bindings/driver.pyx, cuda_bindings/cuda/bindings/runtime.pyx
Both bindings remove callback-data allocation and trampoline wrappers. They pass the callback and user data directly to CUDA.
Graph-replay coverage and lifetime guidance
cuda_bindings/tests/test_cuda.py, cuda_bindings/tests/test_cudart.py, cuda_bindings/docs/source/overview.rst, cuda_bindings/docs/source/release/13.5.0-notes.rst
Tests verify five callback invocations across five graph launches for each API. The overview and release notes describe callback and user-data lifetime requirements.

Assessment against linked issues

Objective Addressed Explanation
[#790] Allow cudaLaunchHostFunc callbacks captured in CUDA graphs to execute on repeated graph replays. ✅

Suggested reviewers: mdboom

Priority: ⬆️ High

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 9d544

No concrete issue remains that should block merging after normal checks.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juenglin
juenglin self-requested a review October 9, 2026 15:14
@juenglin

juenglin commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Does this fix need to be backported to the 12.9.x branch?

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

@mdboom

mdboom commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Does this fix need to be backported to the 12.9.x branch?

Yes. I would apply the to-be-backported label but the bot it triggers doesn't do the right thing. It just needs to be manually backported (with the test + the regenerated bindings with --ctk-target-version 12.9.

@mdboom mdboom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, assuming tests pass.

@juenglin

juenglin commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Follow-ups (not blocking):

  • Backport to 12.9.x, which has the same trampolines.
  • test_cudart_func_callback can't fail: its asserts run inside ctypes callbacks, where exceptions are swallowed. Fix it rather than delete it, since it's the only test of cudaStreamAddCallback.
  • Document that fn and the userData memory must outlive any graph exec containing the node.

@mdboom

mdboom commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Based on this that @juenglin found, I'm retracting my approval, since without that I think the fact that the tests are passing is meaningless.

test_cudart_func_callback can't fail: its asserts run inside ctypes callbacks, where exceptions are swallowed. Fix it rather than delete it, since it's the only test of cudaStreamAddCallback.

@mdboom
mdboom self-requested a review October 9, 2026 20:56

@mdboom mdboom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my comment -- I think we should block on this until the tests don't swallow exceptions.

Keep coverage of cudaStreamAddCallback and cudaLaunchHostFunc while checking callback results on the test thread. Check every captured graph replay and clean up CUDA resources on failure.

Document callback and user data lifetimes for captured graphs.

Signed-off-by: Andy Jost <ajost@nvidia.com>
…nc-trampoline

Signed-off-by: Andy Jost <ajost@nvidia.com>
@Andy-Jost
Andy-Jost requested a review from mdboom October 14, 2026 00:14

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cuda.bindings Everything related to the cuda.bindings module P0 High priority - Must do!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: cudaLaunchHostFunc doesn't work with CUDA Graph

3 participants