Skip to content

Commit 579de9b

Browse files
Add terminate execution API. (#268)
Signed-off-by: chaoqin-li1123 <[email protected]>
1 parent 9cc230f commit 579de9b

File tree

10 files changed

+84
-0
lines changed

10 files changed

+84
-0
lines changed

include/proxy-wasm/null_vm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ struct NullVm : public WasmVm {
6060
FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK)
6161
#undef _REGISTER_CALLBACK
6262

63+
void terminate() override {}
64+
6365
std::string plugin_name_;
6466
std::unique_ptr<NullVmPlugin> plugin_;
6567
};

include/proxy-wasm/wasm_vm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ class WasmVm {
297297
FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK)
298298
#undef _REGISTER_CALLBACK
299299

300+
/**
301+
* Terminate execution of this WasmVM. It shouldn't be used after being terminated.
302+
*/
303+
virtual void terminate() = 0;
304+
300305
bool isFailed() { return failed_ != FailState::Ok; }
301306
void fail(FailState fail_state, std::string_view message) {
302307
integration()->error(message);

src/v8/v8.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
#include <mutex>
2222
#include <optional>
2323
#include <sstream>
24+
#include <thread>
2425
#include <unordered_map>
2526
#include <utility>
2627
#include <vector>
2728

2829
#include "include/v8-version.h"
2930
#include "include/v8.h"
31+
#include "src/wasm/c-api.h"
3032
#include "wasm-api/wasm.hh"
3133

3234
namespace proxy_wasm {
@@ -92,6 +94,8 @@ class V8 : public WasmVm {
9294
FOR_ALL_WASM_VM_EXPORTS(_GET_MODULE_FUNCTION)
9395
#undef _GET_MODULE_FUNCTION
9496

97+
void terminate() override;
98+
9599
private:
96100
std::string getFailMessage(std::string_view function_name, wasm::own<wasm::Trap> trap);
97101

@@ -657,6 +661,16 @@ void V8::getModuleFunctionImpl(std::string_view function_name,
657661
};
658662
}
659663

664+
void V8::terminate() {
665+
auto *store_impl = reinterpret_cast<wasm::StoreImpl *>(store_.get());
666+
auto *isolate = store_impl->isolate();
667+
isolate->TerminateExecution();
668+
while (isolate->IsExecutionTerminating()) {
669+
std::this_thread::yield();
670+
}
671+
integration()->trace("[host->vm] Terminated");
672+
}
673+
660674
std::string V8::getFailMessage(std::string_view function_name, wasm::own<wasm::Trap> trap) {
661675
auto message = "Function: " + std::string(function_name) + " failed: ";
662676
message += std::string(trap->message().get(), trap->message().size());

src/wamr/wamr.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class Wamr : public WasmVm {
8585
};
8686
FOR_ALL_WASM_VM_EXPORTS(_GET_MODULE_FUNCTION)
8787
#undef _GET_MODULE_FUNCTION
88+
89+
void terminate() override {}
90+
8891
private:
8992
template <typename... Args>
9093
void registerHostFunctionImpl(std::string_view module_name, std::string_view function_name,

src/wasmtime/wasmtime.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class Wasmtime : public WasmVm {
9797
void getModuleFunctionImpl(std::string_view function_name,
9898
std::function<R(ContextBase *, Args...)> *function);
9999

100+
void terminate() override {}
101+
100102
WasmStorePtr store_;
101103
WasmModulePtr module_;
102104
WasmSharedModulePtr shared_module_;

src/wavm/wavm.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ struct Wavm : public WasmVm {
229229
FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK)
230230
#undef _REGISTER_CALLBACK
231231

232+
void terminate() override {}
233+
232234
IR::Module ir_module_;
233235
WAVM::Runtime::ModuleRef module_ = nullptr;
234236
WAVM::Runtime::GCPointer<WAVM::Runtime::Instance> module_instance_;

test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ cc_test(
5656
data = [
5757
"//test/test_data:abi_export.wasm",
5858
"//test/test_data:callback.wasm",
59+
"//test/test_data:infinite_loop.wasm",
5960
"//test/test_data:trap.wasm",
6061
],
6162
linkstatic = 1,

test/runtime_test.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <memory>
2020
#include <sstream>
2121
#include <string>
22+
#include <thread>
2223
#include <vector>
2324

2425
#include "include/proxy-wasm/context.h"
@@ -245,6 +246,34 @@ TEST_P(TestVM, Callback) {
245246
ASSERT_EQ(res.u32(), 100100); // 10000 (global) + 100(in callback)
246247
}
247248

249+
TEST_P(TestVM, TerminateExecution) {
250+
// TODO(chaoqin-li1123): implement execution termination for other runtime.
251+
if (engine_ != "v8") {
252+
return;
253+
}
254+
auto source = readTestWasmFile("infinite_loop.wasm");
255+
ASSERT_TRUE(vm_->load(source, {}, {}));
256+
257+
TestContext context;
258+
259+
std::thread terminate([&]() {
260+
std::this_thread::sleep_for(std::chrono::seconds(3));
261+
vm_->terminate();
262+
});
263+
264+
ASSERT_TRUE(vm_->link(""));
265+
WasmCallVoid<0> infinite_loop;
266+
vm_->getFunction("infinite_loop", &infinite_loop);
267+
ASSERT_TRUE(infinite_loop != nullptr);
268+
infinite_loop(&context);
269+
270+
terminate.join();
271+
272+
std::string exp_message = "Function: infinite_loop failed: Uncaught Error: termination_exception";
273+
auto *integration = dynamic_cast<DummyIntegration *>(vm_->integration().get());
274+
ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos);
275+
}
276+
248277
TEST_P(TestVM, Trap) {
249278
auto source = readTestWasmFile("trap.wasm");
250279
ASSERT_TRUE(vm_->load(source, {}, {}));

test/test_data/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ wasm_rust_binary(
3737
srcs = ["trap.rs"],
3838
)
3939

40+
wasm_rust_binary(
41+
name = "infinite_loop.wasm",
42+
srcs = ["infinite_loop.rs"],
43+
)
44+
4045
wasm_rust_binary(
4146
name = "env.wasm",
4247
srcs = ["env.rs"],

test/test_data/infinite_loop.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#[no_mangle]
16+
pub extern "C" fn infinite_loop() {
17+
let mut _count: u64 = 0;
18+
loop {
19+
_count += 1;
20+
}
21+
}

0 commit comments

Comments
 (0)