[vm/isolates] Confirm isolate terminate capability before terminating it.

Fixes https://github.com/dart-lang/sdk/issues/61313
TEST=isolate_restricted_kill_test

Change-Id: I52a41b1c71ceb02c3f91c580dc7939eb3cfae4c8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/445300
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
This commit is contained in:
Alexander Aprelev
2025-08-14 13:16:44 -07:00
committed by Commit Queue
parent fb809c2f92
commit c1caa5c1f6
2 changed files with 54 additions and 1 deletions
@@ -0,0 +1,53 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Verifies that restricted isolate can't be terminated.
//
import 'dart:isolate';
import 'package:expect/async_helper.dart';
import 'package:expect/expect.dart';
main() async {
asyncStart();
int receivedCounter = -1;
final rp = RawReceivePort((value) {
receivedCounter = value;
});
final rpExit = ReceivePort();
final isolate = await Isolate.spawn(
(sendPort) async {
int counter = 0;
while (true) {
sendPort.send(counter++);
await Future.delayed(Duration(milliseconds: 100));
}
},
rp.sendPort,
onExit: rpExit.sendPort,
);
// Wait for the isolate to start.
while (receivedCounter < 0) {
await Future.delayed(Duration(milliseconds: 100));
}
// Create restricted isolate, the one that can't be terminated.
final restricted = Isolate(isolate.controlPort);
restricted.kill();
final before_kill = receivedCounter;
// Wait couple cycles to ensure isolate is still alive.
while (receivedCounter < before_kill + 2) {
await Future.delayed(Duration(milliseconds: 100));
}
// Now kill the original isolate and wait for it to exit.
isolate.kill();
await rpExit.first;
rp.close();
asyncEnd();
}
+1 -1
View File
@@ -1269,9 +1269,9 @@ ErrorPtr IsolateMessageHandler::HandleLibMessage(const Array& message) {
if (!obj.IsSmi()) return Error::null();
const intptr_t priority = Smi::Cast(obj).Value();
if (priority == Isolate::kImmediateAction) {
Thread::Current()->StartUnwindError();
obj = message.At(2);
if (I->VerifyTerminateCapability(obj)) {
Thread::Current()->StartUnwindError();
// We will kill the current isolate by returning an UnwindError.
if (msg_type == Isolate::kKillMsg) {
const String& msg = String::Handle(