53ac68e2dd
Make VM always return empty array in the response. Current implementation for this field comes with a bunch of complexity because it locks message handler and then invokes Dart code which makes it difficult to reason about various invariants. This code is furthermore demonstrated to cause deadlocks. Given that nobody uses it - it is simpler to remove this code altogether. Fixes https://github.com/flutter/flutter/issues/185156 TEST=ci Change-Id: I497210e0f1542860caa0d765d634f8ec6a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/496340 Reviewed-by: Ben Konyi <bkonyi@google.com> Commit-Queue: Slava Egorov <vegorov@google.com>
230 lines
7.2 KiB
C++
230 lines
7.2 KiB
C++
// Copyright (c) 2011, 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_MESSAGE_HANDLER_H_
|
|
#define RUNTIME_VM_MESSAGE_HANDLER_H_
|
|
|
|
#include <memory>
|
|
|
|
#include "vm/isolate.h"
|
|
#include "vm/lockers.h"
|
|
#include "vm/message.h"
|
|
#include "vm/os_thread.h"
|
|
#include "vm/port.h"
|
|
#include "vm/port_set.h"
|
|
#include "vm/thread_pool.h"
|
|
|
|
namespace dart {
|
|
|
|
// A MessageHandler is an entity capable of accepting messages.
|
|
class MessageHandler : public PortHandler {
|
|
protected:
|
|
MessageHandler();
|
|
|
|
public:
|
|
enum MessageStatus {
|
|
kOK, // We successfully handled a message.
|
|
kError, // We encountered an error handling a message.
|
|
kShutdown, // The VM is shutting down.
|
|
};
|
|
static const char* MessageStatusString(MessageStatus status);
|
|
|
|
virtual ~MessageHandler();
|
|
|
|
typedef uword CallbackData;
|
|
typedef void (*EndCallback)(CallbackData data);
|
|
|
|
// Runs this message handler on the thread pool.
|
|
//
|
|
// A message handler will run until it terminates either normally or
|
|
// abnormally. Normal termination occurs when the message handler
|
|
// no longer has any live ports. Abnormal termination occurs when
|
|
// HandleMessage() indicates that an error has occurred during
|
|
// message processing.
|
|
|
|
// Returns false if the handler terminated abnormally, otherwise it
|
|
// returns true.
|
|
bool Run(ThreadPool* pool, EndCallback end_callback, CallbackData data);
|
|
|
|
// Handles the next message for this message handler. Should only
|
|
// be used when not running the handler on the thread pool (via Run
|
|
// or RunBlocking).
|
|
//
|
|
// Returns true on success.
|
|
MessageStatus HandleNextMessage();
|
|
|
|
// Handles any OOB messages for this message handler. Can be used
|
|
// even if the message handler is running on the thread pool.
|
|
//
|
|
// Returns true on success.
|
|
MessageStatus HandleOOBMessages();
|
|
|
|
// Returns true if there are pending OOB messages for this message
|
|
// handler.
|
|
bool HasOOBMessages();
|
|
|
|
#if defined(TESTING)
|
|
std::unique_ptr<Message> StealOOBMessage();
|
|
#endif
|
|
|
|
// Returns true if there are pending normal messages for this message
|
|
// handler.
|
|
bool HasMessages();
|
|
|
|
struct MessageCount {
|
|
intptr_t num_messages;
|
|
intptr_t num_oob_messages;
|
|
};
|
|
|
|
MessageCount GetMessageCounts();
|
|
|
|
// Whether to keep this message handler alive or whether it should shutdown.
|
|
virtual bool KeepAliveLocked() { return true; }
|
|
|
|
bool paused() const { return paused_ > 0; }
|
|
|
|
void increment_paused() { paused_++; }
|
|
void decrement_paused() {
|
|
ASSERT(paused_ > 0);
|
|
paused_--;
|
|
}
|
|
|
|
#if !defined(PRODUCT)
|
|
bool should_pause_on_start() const { return should_pause_on_start_; }
|
|
|
|
void set_should_pause_on_start(bool should_pause_on_start) {
|
|
should_pause_on_start_ = should_pause_on_start;
|
|
}
|
|
|
|
bool is_paused_on_start() const { return is_paused_on_start_; }
|
|
|
|
bool should_pause_on_exit() const { return should_pause_on_exit_; }
|
|
|
|
void set_should_pause_on_exit(bool should_pause_on_exit) {
|
|
should_pause_on_exit_ = should_pause_on_exit;
|
|
}
|
|
|
|
bool is_paused_on_exit() const { return is_paused_on_exit_; }
|
|
|
|
// Timestamp of the paused on start or paused on exit.
|
|
int64_t paused_timestamp() const { return paused_timestamp_; }
|
|
|
|
bool ShouldPauseOnStart(MessageStatus status) const;
|
|
bool ShouldPauseOnExit(MessageStatus status) const;
|
|
void PausedOnStart(bool paused);
|
|
void PausedOnExit(bool paused);
|
|
#endif
|
|
|
|
protected:
|
|
// Custom message notification. Optionally provided by subclass.
|
|
virtual void MessageNotify(Message::Priority priority);
|
|
|
|
// Handles a single message. Provided by subclass.
|
|
//
|
|
// Returns true on success.
|
|
virtual MessageStatus HandleMessage(std::unique_ptr<Message> message) = 0;
|
|
|
|
virtual void NotifyPauseOnStart() {}
|
|
virtual void NotifyPauseOnExit() {}
|
|
|
|
// TODO(iposva): Set a local field before entering MessageHandler methods.
|
|
Thread* thread() const { return Thread::Current(); }
|
|
|
|
// 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;
|
|
|
|
private:
|
|
template <typename GCVisitorType>
|
|
friend void MournFinalizerEntry(GCVisitorType*, FinalizerEntryPtr);
|
|
friend class PortMap;
|
|
friend class MessageHandlerTestPeer;
|
|
friend class MessageHandlerTask;
|
|
|
|
// ------------ START PortMap API ------------
|
|
// These functions should only be called from the PortMap.
|
|
// Implementaion of PortHandler API.
|
|
|
|
const char* name() const override;
|
|
|
|
void OnPortClosed(Dart_Port port) override;
|
|
|
|
void Shutdown() override {
|
|
// Nothing to do.
|
|
}
|
|
|
|
// Return Isolate to which this message handler corresponds to.
|
|
Isolate* isolate() const override { return nullptr; }
|
|
|
|
PortSet<PortSetEntry>* ports(PortMap::Locker& locker) override {
|
|
return &ports_;
|
|
}
|
|
|
|
// Notifies this handler that all ports are being closed.
|
|
void OnAllPortsClosed();
|
|
// ------------ END PortMap API ------------
|
|
|
|
// Called by MessageHandlerTask to process our task queue.
|
|
void TaskCallback();
|
|
|
|
// Checks if we have a slot for idle task execution, if we have a slot
|
|
// for idle task execution it is scheduled immediately or we wait for
|
|
// idle expiration and then attempt to schedule the idle task.
|
|
// Returns true if their is scope for idle task execution so that we
|
|
// can loop back to handle more messages or false if idle tasks are not
|
|
// scheduled.
|
|
bool CheckIfIdleLocked(MonitorLocker* ml);
|
|
|
|
// Triggers a run of the idle task.
|
|
void RunIdleTaskLocked(MonitorLocker* ml);
|
|
|
|
// NOTE: These two functions release and reacquire the monitor, you may
|
|
// need to call HandleMessages to ensure all pending messages are handled.
|
|
void PausedOnStartLocked(MonitorLocker* ml, bool paused);
|
|
void PausedOnExitLocked(MonitorLocker* ml, bool paused);
|
|
|
|
// Dequeue the next message. Prefer messages from the oob_queue_ to
|
|
// messages from the queue_.
|
|
std::unique_ptr<Message> DequeueMessage(Message::Priority min_priority);
|
|
|
|
void ClearOOBQueue();
|
|
|
|
// Handles any pending messages.
|
|
MessageStatus HandleMessages(MonitorLocker* ml,
|
|
bool allow_normal_messages,
|
|
bool allow_multiple_normal_messages);
|
|
|
|
Monitor monitor_; // Protects all fields in MessageHandler.
|
|
MessageQueue* queue_;
|
|
MessageQueue* oob_queue_;
|
|
|
|
// Only accessed by [PortMap], protected by [PortMap]s lock. See ports()
|
|
// getter.
|
|
PortSet<PortSetEntry> ports_;
|
|
|
|
intptr_t paused_; // The number of pause messages received.
|
|
#if !defined(PRODUCT)
|
|
bool should_pause_on_start_;
|
|
bool should_pause_on_exit_;
|
|
bool is_paused_on_start_;
|
|
bool is_paused_on_exit_;
|
|
// When isolate gets paused, remember the status of the message being
|
|
// processed so that we can resume correctly(into potentially not-OK status).
|
|
MessageStatus remembered_paused_on_exit_status_;
|
|
int64_t paused_timestamp_;
|
|
#endif
|
|
bool task_running_;
|
|
ThreadPool* pool_;
|
|
EndCallback end_callback_;
|
|
CallbackData callback_data_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MessageHandler);
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_MESSAGE_HANDLER_H_
|