Skip to content

Conversation

@daniel-wong-dfinity-org
Copy link
Contributor

@daniel-wong-dfinity-org daniel-wong-dfinity-org commented Jan 14, 2026

... and start it again afterwards, of course. Also, lock and unlock he canister.

How

At the core of this PR is a new helper function: exclusively_stop_and_start_canister. It takes a bunch of arguments, but the main one is a function that does the "main" operation, such as taking a snapshot. Meanwhile, the helper takes care of locking and stopping the canister before the main operation, and afterwards, starting, and unlocking it again.

Much code is moved from rs/nns to rs/nervous_system/root.

References

Closes NNS1-4308.

@github-actions github-actions bot added the feat label Jan 14, 2026
…th TakeCanisterSnapshot: moved request and response types from rs/handlers/root/interface to rs/nervous_system/root.
…oot to rs/nervous_system/root, analogous to the previous commit.
@daniel-wong-dfinity-org daniel-wong-dfinity-org force-pushed the stop-before-and-start-after-snapshot-ops-daniel-wong branch 3 times, most recently from 347aa21 to 0ef0b1d Compare January 20, 2026 18:54
…This is a private helper function that will be used in (near) future commits. Its main jobs are

1. Stop canister before main operation, and start it again after the main operation.
2. Acquire a lock on the canister so that different operations do not stomp on each other (and release after)

This pattern is already used during canister upgrades. Therefore, one of the places where this will be used is canister upgrades. The other two places where this will be used in the very near future are taking and loading canister snapshots.
… locks the canister, and stops it before the main operation (i.e. calling the Management canister's `load_canister_snapshot` method), making it safer. (Ofc, the canister is also started after the main operation too, and the lock is released at the very end.) This is implemented with the new helper: `exclusively_stop_and_start_canister`. Next, we'll do the same thing for `take_canister_snapshot`.
…evious commit): acquire canister lock, and stop the canister (ofc, after the main operation, start the canister back up again, and release the lock).|

(This is like the previous commit, which enhanced load_canister_snapshot.)
…lling (take|load)_canister_snapshot. Nobody ever used DfcRuntime in these cases; the ability to choose was just following an existing but depricated pattern.
…oot).

Mainly, changed the implementation of change_canister to use the new exclusively_stop_and_start_canister helper function. Using the helper ensures that code upgrades and snapshottting do not interfere with one another. This also simplifies the implementation of change_canister by factoring out common implementation code.

The other change to change_canister is that the Runtime generic parameter is removed. This is fine because all callers were using CdkRuntime anyway.
@daniel-wong-dfinity-org daniel-wong-dfinity-org force-pushed the stop-before-and-start-after-snapshot-ops-daniel-wong branch from 4bd5451 to a058b35 Compare January 20, 2026 19:22
@daniel-wong-dfinity-org daniel-wong-dfinity-org marked this pull request as ready for review January 20, 2026 19:24
@daniel-wong-dfinity-org daniel-wong-dfinity-org requested a review from a team as a code owner January 20, 2026 19:24
github-actions[bot]

This comment was marked as resolved.

@daniel-wong-dfinity-org daniel-wong-dfinity-org dismissed github-actions[bot]’s stale review January 20, 2026 19:29

These changes are behind a flag.

More precisely, I have changed some Root canister methods that can only be called by the Governance canister, but Governance only calls these to execute proposal types that are currently flag disabled.

Copy link
Contributor

@jasonz-dfinity jasonz-dfinity left a comment

Choose a reason for hiding this comment

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

The title doesn't seem to be accurate, since the PR doesn't involve "governance" (at least not in a way we usually mean)

Comment on lines +209 to +217
/*
let final_err = format!(
"Failed to stop canister {canister_id} while preparing to perform a {operation}: \
{code} {message}. Tried re-starting the canister after that, and the result of \
re-starting was {restart_status}."
);

Err((code, final_err))
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably want to delete this?

}
};

let result = exclusively_stop_and_start_canister::<_, _, _>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I would assume ::<_, _, _> is not needed, but I could be wrong.

@@ -235,7 +235,7 @@ async fn take_canister_snapshot(
take_canister_snapshot_request: TakeCanisterSnapshotRequest,
) -> TakeCanisterSnapshotResponse {
check_caller_is_governance();
canister_management::take_canister_snapshot(
ic_nervous_system_root::take_canister_snapshot::take_canister_snapshot(
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: not sure why we don't stick to importing the symbol instead, especially since use ic_nervous_system_root::... already exists


// Check the result of the install_code
Copy link
Contributor

Choose a reason for hiding this comment

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

Usually I don't like comments just stating what the code does, but here, since the result above is a Result<Result<_, _>, _>, it's probably good to comment on what each error handling does.

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.

2 participants