Skip to content

Commit

Permalink
feat(gstd): Introduce critical hook (#3503)
Browse files Browse the repository at this point in the history
  • Loading branch information
ark0f authored Jan 10, 2024
1 parent 4cc2a23 commit ab427a1
Show file tree
Hide file tree
Showing 12 changed files with 579 additions and 3 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"core-processor",
"core-errors",
"examples/async",
"examples/async-critical",
"examples/async-custom-entry",
"examples/async-init",
"examples/async-signal-entry",
Expand Down Expand Up @@ -367,6 +368,7 @@ try-runtime-cli = { version = "0.10.0-dev", git = "https://github.com/gear-tech/
# Examples
test-syscalls = { path = "examples/syscalls", default-features = false }
demo-async = { path = "examples/async" }
demo-async-critical = { path = "examples/async-critical" }
demo-async-custom-entry = { path = "examples/async-custom-entry" }
demo-async-init = { path = "examples/async-init" }
demo-async-recursion = { path = "examples/async-recursion" }
Expand Down
21 changes: 21 additions & 0 deletions examples/async-critical/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "demo-async-critical"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[dependencies]
gstd.workspace = true
parity-scale-codec.workspace = true
futures.workspace = true

[build-dependencies]
gear-wasm-builder.workspace = true

[features]
debug = ["gstd/debug"]
default = ["std"]
std = []
21 changes: 21 additions & 0 deletions examples/async-critical/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

fn main() {
gear_wasm_builder::build();
}
40 changes: 40 additions & 0 deletions examples/async-critical/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![no_std]

#[cfg(feature = "std")]
mod code {
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
}

#[cfg(feature = "std")]
pub use code::WASM_BINARY_OPT as WASM_BINARY;

use gstd::{Decode, Encode};

#[derive(Debug, Encode, Decode)]
pub enum HandleAction {
Simple,
Panic,
InHandleReply,
InHandleSignal,
}

#[cfg(target_arch = "wasm32")]
mod wasm;
111 changes: 111 additions & 0 deletions examples/async-critical/src/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// This file is part of Gear.

// Copyright (C) 2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::HandleAction;
use gstd::{critical, exec, msg, prelude::*, ActorId};

static mut REPLY_SET_HOOK: bool = false;
static mut SIGNAL_SET_HOOK: bool = false;
static mut INITIATOR: ActorId = ActorId::zero();

#[gstd::async_main(handle_reply = my_handle_reply, handle_signal = my_handle_signal)]
async fn main() {
unsafe { INITIATOR = msg::source() };

let action: HandleAction = msg::load().expect("Failed to read handle action");

match action {
HandleAction::Simple => {
// call `gr_source` outside because it is forbidden in `handle_signal`
let source = msg::source();

// should not send anything because execution will be completed
critical::set_hook(move || {
msg::send_bytes(source, b"critical", 0).unwrap();
});

// wait occurs inside so hook is saved
gstd::msg::send_bytes_for_reply(source, b"for_reply", 0, 0)
.expect("Failed to send message")
.await
.expect("Received error reply");
}
HandleAction::Panic => {
// call `gr_source` outside because it is forbidden in `handle_signal`
let source = msg::source();

// should send message because panic occurs below
critical::set_hook(move || {
msg::send_bytes(source, b"critical", 0).unwrap();
});

// wait occurs inside so hook is saved
gstd::msg::send_bytes_for_reply(msg::source(), b"for_reply", 0, 0)
.expect("Failed to send message")
.await
.expect("Received error reply");

// panic occurs so `handle_signal` will execute hook
panic!();
}
HandleAction::InHandleReply => {
unsafe {
REPLY_SET_HOOK = true;
}

gstd::msg::send_bytes_for_reply(msg::source(), b"for_reply", 0, 0)
.expect("Failed to send message")
.await
.expect("Received error reply");
}
HandleAction::InHandleSignal => {
unsafe {
SIGNAL_SET_HOOK = true;
}

gstd::msg::send_bytes_for_reply(msg::source(), b"for_reply", 0, 0)
.expect("Failed to send message")
.await
.expect("Received error reply");

panic!()
}
}
}

fn my_handle_reply() {
unsafe {
if REPLY_SET_HOOK {
// should panic in this entrypoint
critical::set_hook(move || {
msg::send_bytes(INITIATOR, b"from_handle_reply", 0).unwrap();
});
}
}
}

fn my_handle_signal() {
unsafe {
if SIGNAL_SET_HOOK {
// should panic in this entrypoint
critical::set_hook(move || {
msg::send_bytes(INITIATOR, b"from_handle_signal", 0).unwrap();
});
}
}
}
3 changes: 2 additions & 1 deletion gstd/src/async_runtime/futures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

//! Module for future-management.

use crate::{prelude::Box, MessageId};
use crate::{critical, prelude::Box, MessageId};
use core::{
future::Future,
pin::Pin,
Expand Down Expand Up @@ -87,6 +87,7 @@ where
if Pin::new(&mut task.future).poll(&mut cx).is_ready() {
super::futures().remove(&msg_id);
super::locks().remove_message_entry(msg_id);
let _ = critical::take_hook();
} else {
super::locks().wait(msg_id);
}
Expand Down
8 changes: 6 additions & 2 deletions gstd/src/async_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ mod signals;
mod waker;

pub use self::futures::message_loop;
pub(crate) use locks::Lock;
pub(crate) use signals::ReplyPoll;

use self::futures::FuturesMap;
use crate::critical;
use hashbrown::HashMap;
pub(crate) use locks::Lock;
use locks::LocksMap;
pub(crate) use signals::ReplyPoll;
use signals::WakeSignals;

static mut FUTURES: Option<FuturesMap> = None;
Expand Down Expand Up @@ -58,6 +59,9 @@ pub fn handle_signal() {
let msg_id = crate::msg::signal_from().expect(
"`gstd::async_runtime::handle_signal()` must be called only in `handle_signal` entrypoint",
);

critical::take_and_execute();

futures().remove(&msg_id);
locks().remove_message_entry(msg_id);
}
Loading

0 comments on commit ab427a1

Please sign in to comment.