Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
22043fa
feat(platform-wallet)!: join coordinator threads at shutdown via shar…
lklimek Jul 8, 2026
82d4a43
fix(platform-wallet): close start/shutdown races and surface teardown…
lklimek Jul 9, 2026
855828b
refactor(dash-async): drop unused AtomicFlagGuard/RefcountedFlagGuard…
lklimek Jul 9, 2026
84ce35b
Merge remote-tracking branch 'origin/v4.1-dev' into claudius/3954-mer…
lklimek Jul 9, 2026
84e8d0a
feat(swift-sdk): mirror ErrorShutdownIncomplete = 22 in PlatformWalle…
lklimek Jul 9, 2026
c1d86d9
refactor(platform-wallet): migrate sync coordinators to registry-owne…
lklimek Jul 10, 2026
eb3941c
Merge branch 'v4.1-dev' into feat/platform-wallet-shutdown-join
lklimek Jul 20, 2026
32e665d
fix(platform-wallet): preserve first-pass shutdown failures across de…
lklimek Jul 20, 2026
1d9d23f
Merge remote-tracking branch 'origin/v4.1-dev' into claude/coordinato…
QuantumExplorer Jul 23, 2026
93d0bd4
fix(platform-wallet): bound the shutdown drain phase and fold SPV/pay…
QuantumExplorer Jul 23, 2026
8ec035d
Merge remote-tracking branch 'origin/v4.2-dev' into claude/platform-p…
QuantumExplorer Jul 29, 2026
31e22d5
fix(platform-wallet): hold sync admission across clear/reset and boun…
QuantumExplorer Aug 2, 2026
d3b3f11
feat(platform-wallet): Rust-owned callback contexts for the wallet FFI
QuantumExplorer Aug 2, 2026
56acf2b
refactor(platform-wallet): slim the thread registry to what its consu…
QuantumExplorer Aug 2, 2026
429667e
fix(platform-wallet): count in-flight drains as gate holders; reject …
QuantumExplorer Aug 2, 2026
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ package org.dashfoundation.dashsdk.ffi
*
* [nativeCreate] takes the SDK handle plus the two Kotlin bridge objects
* (persistence + event), builds the native persistence / event vtables
* with boxed `GlobalRef` contexts, hands them to
* `platform_wallet_manager_create_with_persistence_capabilities`, and returns a boxed **bundle** pointer
* as a `jlong`. The bundle owns the two context boxes for the manager's
* lifetime; [nativeDestroy] shuts the manager down (quiescing every
* callback-firing task) and only then frees them.
* with boxed `GlobalRef` contexts, hands them — **with ownership** (the
* vtables carry a `release_fn`) — to
* `platform_wallet_manager_create_with_persistence_capabilities`, and
* returns a boxed **bundle** pointer as a `jlong`. The native manager
* frees each context box exactly once, when its last worker reference
* drops; [nativeDestroy] shuts the manager down (bounded quiesce + join
* of every callback-firing task) and a worker that straggles past it
* keeps its bridge `GlobalRef` alive until that worker exits.
*
* The raw manager `Handle` used by the sync / wallet-accessor calls is
* read from the bundle via [nativeManagerHandle].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,14 @@ class PlatformWalletPersistenceHandler(

/**
* Shut down the owned executor (no-op for an injected dispatcher).
* Callers must quiesce native callbacks first — the manager invokes
* this only after `nativeDestroy` has freed the callback contexts, so
* nothing can dispatch onto the executor afterwards.
* The manager invokes this after `nativeDestroy`'s bounded shutdown
* has quiesced the callback-firing tasks. A native worker that
* straggled past that shutdown holds its own strong reference to the
* bridge (Rust owns the callback context and frees it when the worker
* exits), so a late callback is memory-safe; if it dispatches onto
* the already-closed executor it is rejected and dropped, which is
* fine — every persistence hook is reconciliation-based and re-runs
* on the next launch.
*/
override fun close() {
ownedDispatcher?.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ internal fun initializePlatformWalletNativeManager(
* ## Lifecycle
*
* [AutoCloseable]. [close] stops the sync loops, destroys the native
* bundle (which runs the Rust `shutdown()` — quiescing every callback
* before its context `GlobalRef`s are freed), then closes the resolver +
* signer children. Order matters: the native manager must be torn down
* before the children whose bridges its callbacks reference.
* bundle (which runs the Rust `shutdown()` — a bounded quiesce + join of
* every callback-firing task; the context `GlobalRef`s themselves are
* owned and freed by the native manager when its last worker reference
* drops), then closes the resolver + signer children. Order matters: the
* native manager must be torn down before the children whose bridges its
* callbacks reference.
*
* Blocking natives are wrapped `suspend` / [withContext] `(Dispatchers.IO)`
* and errors pass through `mapNativeErrors` at the public boundary.
Expand Down
4 changes: 3 additions & 1 deletion packages/rs-dash-async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ tracing = "0.1.41"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.40", features = ["rt", "rt-multi-thread", "time", "net"] }
tokio-util = { version = "0.7.12" }
futures = { version = "0.3.30" }

[dev-dependencies]
tokio = { version = "1.40", features = ["macros", "rt-multi-thread", "sync"] }
tokio = { version = "1.40", features = ["macros", "rt-multi-thread", "sync", "time"] }
10 changes: 10 additions & 0 deletions packages/rs-dash-async/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@
//!
//! Provides [`block_on`] -- a function that bridges async futures into sync code,
//! handling multiple tokio runtime flavors (no runtime, current-thread, multi-thread).
//!
//! Also provides `ThreadRegistry` — a shared lifecycle engine for background
//! OS-thread workers (start, cancel, bounded quiesce + join, orphan reap).

mod block_on;
#[cfg(not(target_arch = "wasm32"))]
mod registry;

pub use block_on::{block_on, AsyncError};
#[cfg(not(target_arch = "wasm32"))]
pub use registry::{
ClearingGuard, RegistryKey, ShutdownReport, ThreadRegistry, WorkerConfig, WorkerStatus,
DEFAULT_JOIN_BUDGET, DEFAULT_REAP_BACKSTOP,
};
Loading
Loading