Skip to content

Commit d1fcefc

Browse files
dianamichesacommit-bot@chromium.org
authored andcommitted
[vm] Add Dart_KillIsolate API function.
Also added test. Bug: #37081 Change-Id: Ia7b53fbd2bf7e625e431364e8be55645cc4c56ac Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108404 Reviewed-by: Ryan Macnak <[email protected]> Reviewed-by: Clement Skau <[email protected]> Auto-Submit: Diana-Michesa Rosu <[email protected]> Commit-Queue: Clement Skau <[email protected]>
1 parent 11da803 commit d1fcefc

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

runtime/include/dart_api.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,20 @@ DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate);
10171017
*/
10181018
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate);
10191019

1020+
/**
1021+
* Kills the given isolate.
1022+
*
1023+
* This function has the same effect as dart:isolate's
1024+
* Isolate.kill(priority:immediate).
1025+
* It can interrupt ordinary Dart code but not native code. If the isolate is
1026+
* in the middle of a long running native function, the isolate will not be
1027+
* killed until control returns to Dart.
1028+
*
1029+
* Does not require a current isolate. It is safe to kill the current isolate if
1030+
* there is one.
1031+
*/
1032+
DART_EXPORT void Dart_KillIsolate(Dart_Isolate isolate);
1033+
10201034
/**
10211035
* Notifies the VM that the embedder expects to be idle until |deadline|. The VM
10221036
* may use this time to perform garbage collection or other tasks to avoid

runtime/vm/dart_api_impl.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,12 @@ DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
694694
return Api::IsError(handle);
695695
}
696696

697+
DART_EXPORT void Dart_KillIsolate(Dart_Isolate handle) {
698+
Isolate* isolate = reinterpret_cast<Isolate*>(handle);
699+
CHECK_ISOLATE(isolate);
700+
Isolate::KillIfExists(isolate, Isolate::kKillMsg);
701+
}
702+
697703
DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
698704
Thread* thread = Thread::Current();
699705
TransitionNativeToVM transition(thread);

runtime/vm/dart_api_impl_test.cc

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,80 @@ UNIT_TEST_CASE(DartAPI_DartInitializeCallsCodeObserver) {
8888
EXPECT(Dart_Cleanup() == NULL);
8989
}
9090

91+
TEST_CASE(Dart_KillIsolate) {
92+
const char* kScriptChars =
93+
"int testMain() {\n"
94+
" return 42;\n"
95+
"}\n";
96+
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
97+
EXPECT_VALID(lib);
98+
Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
99+
EXPECT_VALID(result);
100+
int64_t value = 0;
101+
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
102+
EXPECT_EQ(42, value);
103+
Dart_Isolate isolate = reinterpret_cast<Dart_Isolate>(Isolate::Current());
104+
Dart_KillIsolate(isolate);
105+
result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
106+
EXPECT(Dart_IsError(result));
107+
EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
108+
}
109+
110+
class InfiniteLoopTask : public ThreadPool::Task {
111+
public:
112+
InfiniteLoopTask(Dart_Isolate* isolate, Monitor* monitor, bool* interrupted)
113+
: isolate_(isolate), monitor_(monitor), interrupted_(interrupted) {}
114+
virtual void Run() {
115+
TestIsolateScope scope;
116+
const char* kScriptChars =
117+
"testMain() {\n"
118+
" while(true) {};"
119+
"}\n";
120+
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
121+
EXPECT_VALID(lib);
122+
*isolate_ = reinterpret_cast<Dart_Isolate>(Isolate::Current());
123+
{
124+
MonitorLocker ml(monitor_);
125+
ml.Notify();
126+
}
127+
Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
128+
// Test should run an inifinite loop and expect that to be killed.
129+
EXPECT(Dart_IsError(result));
130+
EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
131+
{
132+
MonitorLocker ml(monitor_);
133+
*interrupted_ = true;
134+
ml.Notify();
135+
}
136+
}
137+
138+
private:
139+
Dart_Isolate* isolate_;
140+
Monitor* monitor_;
141+
bool* interrupted_;
142+
};
143+
144+
TEST_CASE(Dart_KillIsolatePriority) {
145+
Monitor monitor;
146+
bool interrupted = false;
147+
Dart_Isolate isolate;
148+
Dart::thread_pool()->Run<InfiniteLoopTask>(&isolate, &monitor, &interrupted);
149+
{
150+
MonitorLocker ml(&monitor);
151+
ml.Wait();
152+
}
153+
154+
Dart_KillIsolate(isolate);
155+
156+
{
157+
MonitorLocker ml(&monitor);
158+
while (!interrupted) {
159+
ml.Wait();
160+
}
161+
}
162+
EXPECT(interrupted);
163+
}
164+
91165
TEST_CASE(DartAPI_ErrorHandleBasics) {
92166
const char* kScriptChars =
93167
"void testMain() {\n"

0 commit comments

Comments
 (0)