Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2020-01-16 19:54:27 +0300
committerShelley Vohr <shelley.vohr@gmail.com>2020-02-17 21:54:19 +0300
commit0cacc1facf77e91affdf69d6c3249aab9838838f (patch)
treedbc5d31ff3a91755fc5526c52221b6acb3b19c04 /src/env.cc
parentf8c45b277fbb59857355d35223c3429005bac6cd (diff)
src: add interrupts to Environments/Workers
Allow doing what V8’s `v8::Isolate::RequestInterrupt()` does for V8. This also works when there is no JS code currently executing. PR-URL: https://github.com/nodejs/node/pull/31386 Refs: https://github.com/openjs-foundation/summit/pull/240 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src/env.cc')
-rw-r--r--src/env.cc41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/env.cc b/src/env.cc
index 35ac40a3d99..f298a7b1a61 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -388,6 +388,8 @@ Environment::Environment(IsolateData* isolate_data,
}
Environment::~Environment() {
+ if (interrupt_data_ != nullptr) *interrupt_data_ = nullptr;
+
isolate()->GetHeapProfiler()->RemoveBuildEmbedderGraphCallback(
BuildEmbedderGraph, this);
@@ -654,11 +656,29 @@ void Environment::AtExit(void (*cb)(void* arg), void* arg) {
at_exit_functions_.push_front(ExitCallback{cb, arg});
}
+void Environment::RunAndClearInterrupts() {
+ while (native_immediates_interrupts_.size() > 0) {
+ NativeImmediateQueue queue;
+ {
+ Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
+ queue.ConcatMove(std::move(native_immediates_interrupts_));
+ }
+ DebugSealHandleScope seal_handle_scope(isolate());
+
+ while (std::unique_ptr<NativeImmediateCallback> head = queue.Shift())
+ head->Call(this);
+ }
+}
+
void Environment::RunAndClearNativeImmediates(bool only_refed) {
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
"RunAndClearNativeImmediates", this);
size_t ref_count = 0;
+ // Handle interrupts first. These functions are not allowed to throw
+ // exceptions, so we do not need to handle that.
+ RunAndClearInterrupts();
+
// It is safe to check .size() first, because there is a causal relationship
// between pushes to the threadsafe and this function being called.
// For the common case, it's worth checking the size first before establishing
@@ -698,6 +718,27 @@ void Environment::RunAndClearNativeImmediates(bool only_refed) {
ToggleImmediateRef(false);
}
+void Environment::RequestInterruptFromV8() {
+ if (interrupt_data_ != nullptr) return; // Already scheduled.
+
+ // The Isolate may outlive the Environment, so some logic to handle the
+ // situation in which the Environment is destroyed before the handler runs
+ // is required.
+ interrupt_data_ = new Environment*(this);
+
+ isolate()->RequestInterrupt([](Isolate* isolate, void* data) {
+ std::unique_ptr<Environment*> env_ptr { static_cast<Environment**>(data) };
+ Environment* env = *env_ptr;
+ if (env == nullptr) {
+ // The Environment has already been destroyed. That should be okay; any
+ // callback added before the Environment shuts down would have been
+ // handled during cleanup.
+ return;
+ }
+ env->interrupt_data_ = nullptr;
+ env->RunAndClearInterrupts();
+ }, interrupt_data_);
+}
void Environment::ScheduleTimer(int64_t duration_ms) {
if (started_cleanup_) return;