Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions pj_plugins/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ submodule-internal modules; `pj_base` carries none).
only `MessageParserPluginBase` + `object_ingest_policy.hpp` live here under
`pj_plugins/sdk/`. (The `docs/ARCHITECTURE.md` §2 diagram is stale on this.)
- **Handles keep the DSO mapped.** Every handle holds a `shared_ptr<void>`
library token, so destroying/hot-reloading the loader cannot `dlclose` a live
plugin. Dialog handles add a non-owning `borrowed()` form for source/toolbox
embedded dialogs — those must not outlive the owning handle.
library token (exposed via `libraryOwner()`), so destroying/hot-reloading the
loader cannot `dlclose` a live plugin — and a lazy ObjectStore payload anchor,
whose `release` fn is plugin code, can capture that token to stay safe past the
handle's own lifetime. Dialog handles add a non-owning `borrowed()` form for
source/toolbox embedded dialogs — those must not outlive the owning handle.

## Read deeper
| For | Read |
Expand Down
5 changes: 4 additions & 1 deletion pj_plugins/docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,10 @@ Each family has a move-only RAII handle:
- Destructor calls `vt->destroy(ctx)`.
- Handles created by a loader retain a shared DSO owner; destroying or
hot-reloading the loader/catalog entry cannot `dlclose` the plugin while
live handles still call its vtable.
live handles still call its vtable. `DataSourceHandle` exposes this token via
`libraryOwner()` so it can be captured anywhere plugin code may outlive the
handle — e.g. a lazy `ObjectStore` payload anchor whose `release` fn lives in
the plugin `.so` — keeping the DSO mapped until that captor is gone too.
- No copy, move-only semantics.
- Methods delegate to vtable functions with the stored context pointer.

Expand Down
8 changes: 8 additions & 0 deletions pj_plugins/include/pj_plugins/host/data_source_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ class DataSourceHandle {
return vt_ != nullptr && ctx_ != nullptr;
}

// The shared library token that keeps this plugin's DSO mapped. Capture a copy
// anywhere a callback or payload anchor PRODUCED BY the plugin may outlive this
// handle (e.g. lazy ObjectStore payloads): the .so must not be dlclosed while
// plugin code (a payload anchor's release fn) can still run.
[[nodiscard]] std::shared_ptr<void> libraryOwner() const {
return library_owner_;
}

[[nodiscard]] std::string manifest() const {
return vt_->manifest_json != nullptr ? std::string(vt_->manifest_json) : std::string();
}
Expand Down
Loading