Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mem-leak): running_swap never shrinks #2301

Merged
merged 6 commits into from
Jan 22, 2025
Merged

Conversation

mariocynicys
Copy link
Collaborator

@mariocynicys mariocynicys commented Dec 23, 2024

this field was convereted to a hashmap instead of a vector for easy access to the swap. also we now manually delete the swap from running swaps when the swap is finished~/inturepted~ (memory leak fix). as a consequence to manuallly deleting the swap from running_swaps, we can now store them as arcs instead of weakrefs, which simplifies a lot of .upgrade() calls.

blocked on its base #2280 re-fixed on top of dev instead

@onur-ozkan
Copy link
Member

onur-ozkan commented Dec 23, 2024

Why is this PR blocked? I can see CI builds are green and commit history doesn't depend on any common commits from other PRs.

@mariocynicys
Copy link
Collaborator Author

Why is this PR blocked? I can see CI builds are green and commit history doesn't depend on any common commits from other PRs.

Nope it depends on history from #2280, no extra commits are showing up here since I am trying to merge into robust-swaps not dev.

Copy link
Member

@borngraced borngraced left a comment

Choose a reason for hiding this comment

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

couple minor notes

Comment on lines 672 to 662
pub fn running_swaps_num(ctx: &MmArc) -> u64 {
let swap_ctx = SwapsContext::from_ctx(ctx).unwrap();
let swaps = swap_ctx.running_swaps.lock().unwrap();
swaps.iter().fold(0, |total, (swap, _)| match swap.upgrade() {
Some(_) => total + 1,
None => total,
})
let count = swap_ctx.running_swaps.lock().unwrap().len();
count as u64
}
Copy link
Member

Choose a reason for hiding this comment

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

let change the return type to usize instead of u64

Comment on lines 704 to 692
for (swap, _) in swaps.values() {
if coins.contains(&swap.maker_coin().to_string()) || coins.contains(&swap.taker_coin().to_string()) {
uuids.push(*swap.uuid())
Copy link
Member

Choose a reason for hiding this comment

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

you can use uuid.extend and filter_map to avoid for loop and push

@onur-ozkan
Copy link
Member

Why is this PR blocked? I can see CI builds are green and commit history doesn't depend on any common commits from other PRs.

Nope it depends on history from #2280, no extra commits are showing up here since I am trying to merge into robust-swaps not dev.

I am not sure what is the purpose of this PR then 🤔

@dimxy
Copy link
Collaborator

dimxy commented Dec 26, 2024

Basically this PR looks good for me: it removes finished or aborted swaps from the running_swaps list.

@mariocynicys mariocynicys changed the base branch from robust-swaps to dev December 29, 2024 13:41
this field was convereted to a hashmap instead of a vector for easy access to the swap also we now manually delete the swap from running swaps when the swap is finished (memory leak fix). as a consequence to manuallly deleting the swap from running_swaps, we can now store them as arcs instead of weakrefs, which simplifies a lot of .upgrade calls.
@mariocynicys
Copy link
Collaborator Author

re-wrote the fix on top of dev. it's not blocked anymore by the original PR from robust-swaps branch.
there is no notion of aborability/stopping of running swaps (only finishing), so that will be covered in the original PR from robust-swaps.

running_swaps: Mutex<Vec<Weak<dyn AtomicSwap>>>,
running_swaps: Mutex<HashMap<Uuid, Arc<dyn AtomicSwap>>>,
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we intentionally chose a weak reference instead of Arc as it might avoid cyclic references (similar to how it's done for MmArc with MmWeak in coins) 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

not that i can trivially find the AtomicSwap pointing back to it self (points to mmctx tho:

)
you see, such questions are really hard to answer in such a codebase and require digging xD
it's much easier/managable to avoid the arc/weak model and use our abortable systems to make sure cyclic refs aren't problematic.

i went for arc here tho since we already manually remove the swap after it finishes or after stopping it. since we drop the thing manually we don't need to complicate it with weak refs.

Copy link
Member

Choose a reason for hiding this comment

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

It's worth to test that change (by using test_mm2_stops_immediately test) to make sure that's not the case.

@onur-ozkan onur-ozkan force-pushed the running-swaps-memleak branch from a4e7c75 to fbd5e9f Compare January 8, 2025 07:44
@onur-ozkan
Copy link
Member

Force pushed to re-trigger CI.

THERE ARE NO RUNNING SWAPS
theoretically we don't need to clear it on native targets since the executable will terminate even without clearing, but for wasm the story isn't exactly the same, i presume
@laruh laruh added the priority: high Important tasks that need attention soon. label Jan 16, 2025
@@ -655,13 +655,9 @@ pub fn get_locked_amount(ctx: &MmArc, coin: &str) -> MmNumber {
}

/// Get number of currently running swaps
Copy link
Collaborator Author

@mariocynicys mariocynicys Jan 16, 2025

Choose a reason for hiding this comment

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

fix this doc comment
also consider clearing the running swap on mmctx destructor/stop method instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

also i wanted to clear the swaps in MmCtx::stop instead since that's how we destruct MmCtx. but that won't work because we have no access to SwapsContext data type.

Comment on lines +660 to +662
pub fn clear_running_swaps(ctx: &MmArc) {
let swap_ctx = SwapsContext::from_ctx(ctx).unwrap();
let swaps = swap_ctx.running_swaps.lock().unwrap();
swaps.iter().fold(0, |total, swap| match swap.upgrade() {
Some(_) => total + 1,
None => total,
})
swap_ctx.running_swaps.lock().unwrap().clear();
Copy link
Member

Choose a reason for hiding this comment

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

Does clearing the map stops swap processes?

Copy link
Collaborator Author

@mariocynicys mariocynicys Jan 21, 2025

Choose a reason for hiding this comment

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

yup. the store of running_swaps stores the swaps (AtomicSwap object) along with the abort handles (which will trigger on Drop) they are running on.
messed things, look at: #2301 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Can you please mention that on the code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

/// Clear up all the running swaps.
///
/// This also auto-stops any running swaps since their abort handles will get triggered (assuming these abort handles aren't already triggered by other means).
pub fn clear_running_swaps(ctx: &MmArc) {

it's already in the doc comment. or u mean somewhere else?

Copy link
Member

Choose a reason for hiding this comment

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

Ah didn't see that. I was referring to caller side but it's fine

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

big ooops:

yup. the store of running_swaps stores the swaps (AtomicSwap object) along with the abort handles (which will trigger on Drop) they are running on.

this is completely wrong. this feat is in another PR. i mixed things up.

no, clearing the running swaps will not stop these swaps. (though could be stopped via other means, e.g. abort_all from a bigger subsystem).

Copy link
Member

Choose a reason for hiding this comment

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

Ok that is def. worth to mention that on the line.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I tried this code, looks like clear_running_swaps fn is needed to clear swaps_ctx in MmCtx to allow to release ctx so stop_and_wait_for_ctx_is_dropped fn can finish (used in wasm tests).

(this note to memorise)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated the doc comment accordingly till the other PR that stores the abort handle lands in.

onur-ozkan
onur-ozkan previously approved these changes Jan 21, 2025
@dimxy
Copy link
Collaborator

dimxy commented Jan 21, 2025

I am okay with this PR.
I see @borngraced has changes suggested, and we could merge it after this is resolved.

borngraced
borngraced previously approved these changes Jan 21, 2025
@mariocynicys mariocynicys dismissed stale reviews from borngraced and onur-ozkan via 64a0012 January 22, 2025 10:46
@borngraced
Copy link
Member

I am okay with this PR. I see @borngraced has changes suggested, and we could merge it after this is resolved.

Seems the changes to the code were reverted. So I approved

@shamardy shamardy merged commit da29651 into dev Jan 22, 2025
19 of 23 checks passed
@shamardy shamardy deleted the running-swaps-memleak branch January 22, 2025 17:31
shamardy pushed a commit that referenced this pull request Jan 28, 2025
shamardy pushed a commit that referenced this pull request Jan 30, 2025
shamardy pushed a commit that referenced this pull request Jan 30, 2025
dimxy added a commit to dimxy/komodo-defi-framework that referenced this pull request Feb 4, 2025
* dev:
  fix(hash-types): remove panic, enforce fixed-size arrays (KomodoPlatform#2279)
  fix(ARRR): store unconfirmed change output (KomodoPlatform#2276)
  feat(tendermint): staking/delegation (KomodoPlatform#2322)
  chore(deps): `timed-map` migration (KomodoPlatform#2247)
  fix(mem-leak): `running_swap` never shrinks (KomodoPlatform#2301)
  chore(dep-bump): libp2p (KomodoPlatform#2326)
  refactor(build script): rewrite the main build script (KomodoPlatform#2319)
dimxy added a commit to dimxy/komodo-defi-framework that referenced this pull request Feb 4, 2025
* dev:
  fix(hash-types): remove panic, enforce fixed-size arrays (KomodoPlatform#2279)
  fix(ARRR): store unconfirmed change output (KomodoPlatform#2276)
  feat(tendermint): staking/delegation (KomodoPlatform#2322)
  chore(deps): `timed-map` migration (KomodoPlatform#2247)
  fix(mem-leak): `running_swap` never shrinks (KomodoPlatform#2301)
  chore(dep-bump): libp2p (KomodoPlatform#2326)
  refactor(build script): rewrite the main build script (KomodoPlatform#2319)
dimxy added a commit that referenced this pull request Feb 16, 2025
* dev:
  fix(derive_key_from_path): check length of current_key_material (#2356)
  chore(release): bump mm2 version to 2.4.0-beta (#2346)
  fix(tests): add additional testnet sepolia nodes to test code (#2358)
  fix(swaps): maintain legacy compatibility for negotiation messages (#2353)
  refactor(SwapOps): impl defaults for protocol specific swapops fns (#2354)
  feat(tpu-v2): provide swap protocol versioning (#2324)
  feat(wallet): add change mnemonic password rpc (#2317)
  fix(tpu-v2): fix tpu-v2 wait for payment spend and extract secret (#2261)
  feat(tendermint): unstaking/undelegation (#2330)
  fix(utxo-withdraw): get hw ctx only when `PrivKeyPolicy` is trezor (#2333)
  feat(event-streaming): API-driven subscription management (#2172)
  fix(hash-types): remove panic, enforce fixed-size arrays (#2279)
  fix(ARRR): store unconfirmed change output (#2276)
  feat(tendermint): staking/delegation (#2322)
  chore(deps): `timed-map` migration (#2247)
  fix(mem-leak): `running_swap` never shrinks (#2301)
  chore(dep-bump): libp2p (#2326)
  refactor(build script): rewrite the main build script (#2319)
dimxy added a commit that referenced this pull request Feb 16, 2025
* dev:
  fix(derive_key_from_path): check length of current_key_material (#2356)
  chore(release): bump mm2 version to 2.4.0-beta (#2346)
  fix(tests): add additional testnet sepolia nodes to test code (#2358)
  fix(swaps): maintain legacy compatibility for negotiation messages (#2353)
  refactor(SwapOps): impl defaults for protocol specific swapops fns (#2354)
  feat(tpu-v2): provide swap protocol versioning (#2324)
  feat(wallet): add change mnemonic password rpc (#2317)
  fix(tpu-v2): fix tpu-v2 wait for payment spend and extract secret (#2261)
  feat(tendermint): unstaking/undelegation (#2330)
  fix(utxo-withdraw): get hw ctx only when `PrivKeyPolicy` is trezor (#2333)
  feat(event-streaming): API-driven subscription management (#2172)
  fix(hash-types): remove panic, enforce fixed-size arrays (#2279)
  fix(ARRR): store unconfirmed change output (#2276)
  feat(tendermint): staking/delegation (#2322)
  chore(deps): `timed-map` migration (#2247)
  fix(mem-leak): `running_swap` never shrinks (#2301)
  chore(dep-bump): libp2p (#2326)
  refactor(build script): rewrite the main build script (#2319)
dimxy added a commit to dimxy/komodo-defi-framework that referenced this pull request Feb 24, 2025
* dev: (24 commits)
  fix(eth-tpu): remove state from funding validation (KomodoPlatform#2334)
  improvement(rpc-server): rpc server dynamic port allocation (KomodoPlatform#2342)
  fix(tests): fix or ignore unstable tests (KomodoPlatform#2365)
  fix(fs): make `filter_files_by_extension` return only files (KomodoPlatform#2364)
  fix(derive_key_from_path): check length of current_key_material (KomodoPlatform#2356)
  chore(release): bump mm2 version to 2.4.0-beta (KomodoPlatform#2346)
  fix(tests): add additional testnet sepolia nodes to test code (KomodoPlatform#2358)
  fix(swaps): maintain legacy compatibility for negotiation messages (KomodoPlatform#2353)
  refactor(SwapOps): impl defaults for protocol specific swapops fns (KomodoPlatform#2354)
  feat(tpu-v2): provide swap protocol versioning (KomodoPlatform#2324)
  feat(wallet): add change mnemonic password rpc (KomodoPlatform#2317)
  fix(tpu-v2): fix tpu-v2 wait for payment spend and extract secret (KomodoPlatform#2261)
  feat(tendermint): unstaking/undelegation (KomodoPlatform#2330)
  fix(utxo-withdraw): get hw ctx only when `PrivKeyPolicy` is trezor (KomodoPlatform#2333)
  feat(event-streaming): API-driven subscription management (KomodoPlatform#2172)
  fix(hash-types): remove panic, enforce fixed-size arrays (KomodoPlatform#2279)
  fix(ARRR): store unconfirmed change output (KomodoPlatform#2276)
  feat(tendermint): staking/delegation (KomodoPlatform#2322)
  chore(deps): `timed-map` migration (KomodoPlatform#2247)
  fix(mem-leak): `running_swap` never shrinks (KomodoPlatform#2301)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: high Important tasks that need attention soon. status: pending review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants