Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: crash on x86_64 systems that support memory protection keys #1318

Merged
merged 3 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <memory>

#include "support.h"
#include "unicode/locid.h"
Expand All @@ -17,9 +19,12 @@
#include "v8/include/v8.h"
#include "v8/src/api/api-inl.h"
#include "v8/src/api/api.h"
#include "v8/src/base/debug/stack_trace.h"
#include "v8/src/base/sys-info.h"
#include "v8/src/execution/isolate-utils-inl.h"
#include "v8/src/execution/isolate-utils.h"
#include "v8/src/flags/flags.h"
#include "v8/src/libplatform/default-platform.h"
#include "v8/src/objects/objects-inl.h"
#include "v8/src/objects/objects.h"
#include "v8/src/objects/smi.h"
Expand Down Expand Up @@ -2579,6 +2584,49 @@ v8::StartupData v8__SnapshotCreator__CreateBlob(
return self->CreateBlob(function_code_handling);
}

class UnprotectedDefaultPlatform : public v8::platform::DefaultPlatform {
using IdleTaskSupport = v8::platform::IdleTaskSupport;
using InProcessStackDumping = v8::platform::InProcessStackDumping;
using PriorityMode = v8::platform::PriorityMode;
using TracingController = v8::TracingController;

static constexpr int kMaxThreadPoolSize = 16;

public:
explicit UnprotectedDefaultPlatform(
int thread_pool_size, IdleTaskSupport idle_task_support,
std::unique_ptr<TracingController> tracing_controller = {},
PriorityMode priority_mode = PriorityMode::kDontApply)
: v8::platform::DefaultPlatform(thread_pool_size, idle_task_support,
std::move(tracing_controller),
priority_mode) {}

static std::unique_ptr<v8::Platform> New(
int thread_pool_size, IdleTaskSupport idle_task_support,
InProcessStackDumping in_process_stack_dumping,
std::unique_ptr<TracingController> tracing_controller = {},
PriorityMode priority_mode = PriorityMode::kDontApply) {
// This implementation is semantically equivalent to the implementation of
// `v8::platform::NewDefaultPlatform()`.
DCHECK_GE(thread_pool_size, 0);
if (thread_pool_size < 1) {
thread_pool_size =
std::max(v8::base::SysInfo::NumberOfProcessors() - 1, 1);
}
thread_pool_size = std::min(thread_pool_size, kMaxThreadPoolSize);
if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
v8::base::debug::EnableInProcessStackDumping();
}
return std::make_unique<UnprotectedDefaultPlatform>(
thread_pool_size, idle_task_support, std::move(tracing_controller),
priority_mode);
}

v8::ThreadIsolatedAllocator* GetThreadIsolatedAllocator() override {
return nullptr;
}
};

v8::Platform* v8__Platform__NewDefaultPlatform(int thread_pool_size,
bool idle_task_support) {
return v8::platform::NewDefaultPlatform(
Expand All @@ -2589,6 +2637,16 @@ v8::Platform* v8__Platform__NewDefaultPlatform(int thread_pool_size,
.release();
}

v8::Platform* v8__Platform__NewUnprotectedDefaultPlatform(
int thread_pool_size, bool idle_task_support) {
return UnprotectedDefaultPlatform::New(
thread_pool_size,
idle_task_support ? v8::platform::IdleTaskSupport::kEnabled
: v8::platform::IdleTaskSupport::kDisabled,
v8::platform::InProcessStackDumping::kDisabled, nullptr)
.release();
}

v8::Platform* v8__Platform__NewSingleThreadedDefaultPlatform(
bool idle_task_support) {
return v8::platform::NewSingleThreadedDefaultPlatform(
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ pub use module::*;
pub use object::*;
pub use platform::new_default_platform;
pub use platform::new_single_threaded_default_platform;
pub use platform::new_unprotected_default_platform;
pub use platform::Platform;
pub use primitives::*;
pub use private::*;
Expand Down
35 changes: 35 additions & 0 deletions src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ extern "C" {
thread_pool_size: int,
idle_task_support: bool,
) -> *mut Platform;
fn v8__Platform__NewUnprotectedDefaultPlatform(
thread_pool_size: int,
idle_task_support: bool,
) -> *mut Platform;
fn v8__Platform__NewSingleThreadedDefaultPlatform(
idle_task_support: bool,
) -> *mut Platform;
Expand Down Expand Up @@ -58,6 +62,10 @@ pub struct Platform(Opaque);
/// If |idle_task_support| is enabled then the platform will accept idle
/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
/// calling v8::platform::RunIdleTasks to process the idle tasks.
///
/// TODO: reference the threading restrictions that apply when V8 is initialized
/// with the default platform, the implications for the Cargo test harness, and
/// when to use new_unprotected_default_platform().
piscisaureus marked this conversation as resolved.
Show resolved Hide resolved
#[inline(always)]
pub fn new_default_platform(
thread_pool_size: u32,
Expand All @@ -66,6 +74,15 @@ pub fn new_default_platform(
Platform::new(thread_pool_size, idle_task_support)
}

/// TODO: doc comment
#[inline(always)]
piscisaureus marked this conversation as resolved.
Show resolved Hide resolved
pub fn new_unprotected_default_platform(
thread_pool_size: u32,
idle_task_support: bool,
) -> UniqueRef<Platform> {
Platform::new_unprotected(thread_pool_size, idle_task_support)
}

/// The same as new_default_platform() but disables the worker thread pool.
/// It must be used with the --single-threaded V8 flag.
///
Expand All @@ -88,6 +105,10 @@ impl Platform {
/// If |idle_task_support| is enabled then the platform will accept idle
/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
/// calling v8::platform::RunIdleTasks to process the idle tasks.
///
/// TODO: reference the threading restrictions that apply when V8 is
/// initialized with the default platform, the implications for the Cargo
/// test harness, and when to use new_unprotected().
piscisaureus marked this conversation as resolved.
Show resolved Hide resolved
#[inline(always)]
pub fn new(
thread_pool_size: u32,
Expand All @@ -101,6 +122,20 @@ impl Platform {
}
}

/// TODO: doc comment
#[inline(always)]
piscisaureus marked this conversation as resolved.
Show resolved Hide resolved
pub fn new_unprotected(
thread_pool_size: u32,
idle_task_support: bool,
) -> UniqueRef<Self> {
unsafe {
UniqueRef::from_raw(v8__Platform__NewUnprotectedDefaultPlatform(
thread_pool_size.min(16) as i32,
idle_task_support,
))
}
}

/// The same as new() but disables the worker thread pool.
/// It must be used with the --single-threaded V8 flag.
///
Expand Down
2 changes: 1 addition & 1 deletion tests/slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn setup() {
START.call_once(|| {
v8::V8::set_flags_from_string("--expose_gc");
v8::V8::initialize_platform(
v8::new_default_platform(0, false).make_shared(),
v8::new_unprotected_default_platform(0, false).make_shared(),
);
v8::V8::initialize();
});
Expand Down
2 changes: 1 addition & 1 deletion tests/test_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mod setup {
"--no_freeze_flags_after_init --expose_gc --harmony-import-assertions --harmony-shadow-realm --allow_natives_syntax --turbo_fast_api_calls",
);
v8::V8::initialize_platform(
v8::new_default_platform(0, false).make_shared(),
v8::new_unprotected_default_platform(0, false).make_shared(),
);
v8::V8::initialize();
});
Expand Down
4 changes: 3 additions & 1 deletion tests/test_api_entropy_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ fn set_entropy_source() {
true
});

v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
v8::V8::initialize_platform(
v8::new_unprotected_default_platform(0, false).make_shared(),
);
v8::V8::initialize();

// Assumes that every isolate creates a PRNG from scratch, which is currently true.
Expand Down
4 changes: 3 additions & 1 deletion tests/test_api_flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#[test]
fn set_flags_from_string() {
v8::V8::set_flags_from_string("--use_strict");
v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
v8::V8::initialize_platform(
v8::new_unprotected_default_platform(0, false).make_shared(),
);
v8::V8::initialize();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
Expand Down
4 changes: 3 additions & 1 deletion tests/test_platform_atomics_pump_message_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ fn atomics_pump_message_loop() {
v8::V8::set_flags_from_string(
"--allow-natives-syntax --harmony-sharedarraybuffer",
);
v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
v8::V8::initialize_platform(
v8::new_unprotected_default_platform(0, false).make_shared(),
);
v8::V8::initialize();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
Expand Down
Loading