Skip to content

fix: Put a sentinel in the native thread local error slot - #312

Draft
tmathern wants to merge 8 commits into
mathern/sigsev-sigabortfrom
mathern/error-slot-sentinel
Draft

fix: Put a sentinel in the native thread local error slot#312
tmathern wants to merge 8 commits into
mathern/sigsev-sigabortfrom
mathern/error-slot-sentinel

Conversation

@tmathern

@tmathern tmathern commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Changes in this pull request

After a consuming native call fails, the Python side decides whether the handle was taken by reading the last native error and matching it against the pre-consume tags (UntrackedPointer:, WrongPointerType:). That slot is thread-local (cimpl_error.rs, LAST_ERROR) and sticky: nothing clears it between calls. A pooled worker thread therefore carries whatever error it last set, across unrelated tasks. A later failure that does not set its own error reads a tag from a task that finished long ago. THis leads to wrong decisions regarding what to release actually when.

This is especially problematic if an address was reused (which can happen under heavier load): the registry rejects an
address it no longer tracks, unless another thread has allocated a fresh tracked object at that exact address, in which case the stale free finds a live entry and destroys a different thread's object.

Repeated allocation and release of similarly sized objects is precisely the pattern that makes an allocator hand back an address it just freed. This leads either to bad references, or allocator-detected corruptions.

Put a sentinel in the error slot so the failing path can be identified, and to make sure no stale error is visible (which could lead to the wrong memory release decisions).

As a sidenote: On any consume failure where the verdict is not certain, this takes the consumed branch, meaning leaks could appear. Also, note this will disappear with v0.91.0 of c2pa-rs, which clarifies the consumption status of pointers (always consumed by native calls), make sure the leak situation can't happen anymore. It is still worthwhile to consider this fix, to ensure no stale errors are read by churning threads.

Checklist

  • This PR represents a single feature, fix, or change.
  • All applicable changes have been documented.
  • Any TO DO items (or similar) have been entered as GitHub issues and the link to that issue has been included in a comment.

@tmathern tmathern self-assigned this Aug 25, 2026
@tmathern tmathern changed the title fix: Put a sentinel in the error slot so no stale error can be read fix: Put a sentinel in the native thread local error slot Aug 25, 2026
@tmathern
tmathern marked this pull request as draft August 25, 2026 06:03
@tmathern
tmathern force-pushed the mathern/error-slot-sentinel branch from 81fed3d to ac6a4da Compare August 25, 2026 22:02
@tmathern
tmathern changed the base branch from main to mathern/sigsev-sigabort August 25, 2026 22:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant