Skip to content

fix(plugin)!: panic safety - #84

Merged
poiana merged 11 commits into
falcosecurity:mainfrom
gnosek:panic-safe
Jun 3, 2026
Merged

poiana merged 11 commits into
falcosecurity:mainfrom
gnosek:panic-safe

Conversation

@gnosek

@gnosek gnosek commented May 28, 2026

Copy link
Copy Markdown
Collaborator
  • Switch to C ABI (C-unwind was a misunderstanding on my side)
  • catch_unwind to convert panics in plugins into API-level errors
  • limit the blast radius of the thread pool implementation (occasional crashes reduced to even more occasional small memory leaks)
  • remove ThreadPool::unsubscribe

What type of PR is this?

Uncomment one (or more) /kind <> lines:

/kind bug

/kind cleanup

/kind design

/kind documentation

/kind failing-test

/kind feature

Any specific area of the project related to this PR?

Uncomment one (or more) /area <> lines:

/area build

/area automation

/area event

/area event_derive

/area plugin

/area plugin_api

/area plugin_derive

/area plugin_tests

What this PR does / why we need it:

Which issue(s) this PR fixes:

Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

NONE

gnosek added 11 commits May 28, 2026 15:37
Using "C-unwind" was the result of confusion about panic handling,
it's not safe to unwind into C++ code under (sinsp) under
any circumstances.

Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Previously, Routine was an opaque handle with no built-in unsubscribe —
callers had to manually call ThreadPool::unsubscribe and were warned to
use ManuallyDrop to avoid unsafety. The closure was a bare Box<F> passed
as the thread pool's data pointer, with no coordination between drop and
the callback.

Redesign Routine::drop to automatically unsubscribe and free the closure,
using an atomic phase protocol to coordinate with the callback:

  The closure (Box<F>) and the coordination state (Arc<SharedState>) are
  separate allocations. SharedState holds an AtomicUsize phase flag, a
  type-erased pointer to the closure, and a typed destructor. The thread
  pool receives Arc::into_raw(SharedState) as its data pointer; Routine
  holds its own Arc clone.

  Three phase states — IDLE, RUNNING, DROP_REQUESTED — determine who
  frees the closure:

  - cb_wrapper: borrows the raw Arc via from_raw/clone/forget (leaving
    the raw refcount undisturbed), then swaps RUNNING into phase. If it
    sees DROP_REQUESTED, the closure is already freed — return 0. After
    executing the closure, CAS RUNNING→IDLE; if that fails (drop set
    DROP_REQUESTED), free the closure and reclaim the raw Arc refcount.
    On Break (return 0), also reclaim the raw refcount since the
    framework won't call again.

  - Routine::drop: calls unsubscribe, then swaps DROP_REQUESTED into
    phase. If previous value was IDLE, free the closure. If RUNNING,
    the callback will handle cleanup on return.

  Known leak: Routine::drop does not reclaim the thread pool's Arc
  clone of SharedState, because a callback may have been dispatched but
  not yet entered cb_wrapper (the framework provides no "drain" hook).
  This is bounded — just the SharedState (AtomicUsize + two pointers +
  Arc overhead). The closure itself (which may capture arbitrarily large
  state) is always freed.

Also remove ThreadPool::unsubscribe — unsubscription is now automatic.
Routine is #[must_use] to prevent accidental immediate drops.

Signed-off-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>

@ekoops ekoops 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.

/approve

@poiana

poiana commented Jun 3, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ekoops, gnosek

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@poiana

poiana commented Jun 3, 2026

Copy link
Copy Markdown

LGTM label has been added.

DetailsGit tree hash: 4d2c1566808b88903373d779677fd0f8a7cf9d04

@poiana
poiana merged commit e068732 into falcosecurity:main Jun 3, 2026
7 checks passed
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.

3 participants