Files
sdk/runtime/vm/native_message_handler.h
Alexander Aprelev 5a98fe5564 [vm/isolates] Avoid leaving isolate as part of native message handling.
Letting isolate go seems to be problematic. If this native messaging api is used during runtime call, then original isolate might end up on a different worker os thread causing remembered frame pointer(remembered as part of entering runtime call) to become invalid due to different stack bounds of this new thread. Invalid frame pointer causes immediate assertion failures during stack walk done for GC purposes or for exception handling.

TEST=ci, https://dart-review.git.corp.google.com/c/sdk/+/486522/comments/ee54d99f_a5c2a9d4

Change-Id: If69076bb9e107502dfef819de73829d9682bb134
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501220
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
2026-05-06 14:42:04 -07:00

76 lines
2.4 KiB
C++

// Copyright (c) 2012, 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.
#ifndef RUNTIME_VM_NATIVE_MESSAGE_HANDLER_H_
#define RUNTIME_VM_NATIVE_MESSAGE_HANDLER_H_
#include <memory>
#include "include/dart_api.h"
#include "include/dart_native_api.h"
#include "vm/message_handler.h"
namespace dart {
// A NativeMessageHandler accepts messages and dispatches them to
// native C handlers on worker threads. It will spawn up to
// |max_concurrency| worker threads which will handle incomming messages
// concurrently.
class NativeMessageHandler final : public PortHandler {
public:
NativeMessageHandler(const char* name,
Dart_NativeMessageHandler func,
intptr_t max_concurrency);
~NativeMessageHandler() override;
const char* name() const override { return name_.get(); }
Dart_NativeMessageHandler func() const { return func_; }
void OnPortClosed(Dart_Port port) override {}
Isolate* isolate() const override { return nullptr; }
// Posts a message on this handler's message queue.
// If before_events is true, then the message is enqueued before any pending
// events, but after any pending isolate library events.
void PostMessage(std::unique_ptr<Message> message,
bool before_events = false) override;
// Request deletion of the given handler once it is down with the currently
// running Dart_NativeMessageHandler callbacks. No new callbacks will be
// scheduled after this call.
//
// |handler| might be deleted synchronously if no callback is running,
// or it can be deleted later on a worker thread.
//
// |RequestDeletion| should be called after |Init| but before |Cleanup|.
// |Cleanup| will wait for all pending deletions to complete - which allows
// VM to shutdown cleanly.
static void RequestDeletion(NativeMessageHandler* handler);
void Shutdown() override;
static void Init();
static void Cleanup();
private:
PortSet<PortSetEntry>* ports(PortMap::Locker& locker) override {
return nullptr;
}
static Monitor* monitor_;
static intptr_t pending_deletions_;
CStringUniquePtr name_;
const Dart_NativeMessageHandler func_;
ThreadPool pool_;
};
} // namespace dart
#endif // RUNTIME_VM_NATIVE_MESSAGE_HANDLER_H_