Skip to content

Commit

Permalink
trace_event: destroy platform before tracing
Browse files Browse the repository at this point in the history
For safer shutdown, we should destroy the platform – and background
threads - before the tracing infrastructure is destroyed. This change
fixes the relative order of NodePlatform disposition and the tracing
agent shutting down. This matches the nesting order for startup.

Make the tracing agent own the tracing controller instead of platform
to match the above.

Fixes: nodejs#22865
  • Loading branch information
ofrobots committed Sep 20, 2018
1 parent 3cb663a commit 7139e97
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 14 deletions.
5 changes: 4 additions & 1 deletion src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,18 @@ static struct {
controller->AddTraceStateObserver(new NodeTraceStateObserver(controller));
tracing::TraceEventHelper::SetTracingController(controller);
StartTracingAgent();
// Tracing must be initialized before platform threads are created.
platform_ = new NodePlatform(thread_pool_size, controller);
V8::InitializePlatform(platform_);
}

void Dispose() {
tracing_agent_.reset(nullptr);
platform_->Shutdown();
delete platform_;
platform_ = nullptr;
// Destroy tracing after the platform (and platform threads) have been
// stopped.
tracing_agent_.reset(nullptr);
}

void DrainVMTasks(Isolate* isolate) {
Expand Down
7 changes: 3 additions & 4 deletions src/node_platform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,9 @@ int PerIsolatePlatformData::unref() {
NodePlatform::NodePlatform(int thread_pool_size,
TracingController* tracing_controller) {
if (tracing_controller) {
tracing_controller_.reset(tracing_controller);
tracing_controller_ = tracing_controller;
} else {
TracingController* controller = new TracingController();
tracing_controller_.reset(controller);
tracing_controller_ = new TracingController();
}
worker_thread_task_runner_ =
std::make_shared<WorkerThreadsTaskRunner>(thread_pool_size);
Expand Down Expand Up @@ -423,7 +422,7 @@ double NodePlatform::CurrentClockTimeMillis() {
}

TracingController* NodePlatform::GetTracingController() {
return tracing_controller_.get();
return tracing_controller_;
}

template <class T>
Expand Down
2 changes: 1 addition & 1 deletion src/node_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class NodePlatform : public MultiIsolatePlatform {
std::unordered_map<v8::Isolate*,
std::shared_ptr<PerIsolatePlatformData>> per_isolate_;

std::unique_ptr<v8::TracingController> tracing_controller_;
v8::TracingController* tracing_controller_;
std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_;
};

Expand Down
11 changes: 5 additions & 6 deletions src/tracing/agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ using v8::platform::tracing::TraceConfig;
using v8::platform::tracing::TraceWriter;
using std::string;

Agent::Agent() {
tracing_controller_ = new TracingController();
Agent::Agent() : tracing_controller_(new TracingController()) {
tracing_controller_->Initialize(nullptr);

CHECK_EQ(uv_loop_init(&tracing_loop_), 0);
Expand Down Expand Up @@ -117,7 +116,7 @@ AgentWriterHandle Agent::AddClient(
use_categories = &categories_with_default;
}

ScopedSuspendTracing suspend(tracing_controller_, this);
ScopedSuspendTracing suspend(tracing_controller_.get(), this);
int id = next_writer_id_++;
AsyncTraceWriter* raw = writer.get();
writers_[id] = std::move(writer);
Expand Down Expand Up @@ -157,7 +156,7 @@ void Agent::Disconnect(int client) {
Mutex::ScopedLock lock(initialize_writer_mutex_);
to_be_initialized_.erase(writers_[client].get());
}
ScopedSuspendTracing suspend(tracing_controller_, this);
ScopedSuspendTracing suspend(tracing_controller_.get(), this);
writers_.erase(client);
categories_.erase(client);
}
Expand All @@ -166,13 +165,13 @@ void Agent::Enable(int id, const std::set<std::string>& categories) {
if (categories.empty())
return;

ScopedSuspendTracing suspend(tracing_controller_, this,
ScopedSuspendTracing suspend(tracing_controller_.get(), this,
id != kDefaultHandleId);
categories_[id].insert(categories.begin(), categories.end());
}

void Agent::Disable(int id, const std::set<std::string>& categories) {
ScopedSuspendTracing suspend(tracing_controller_, this,
ScopedSuspendTracing suspend(tracing_controller_.get(), this,
id != kDefaultHandleId);
std::multiset<std::string>& writer_categories = categories_[id];
for (const std::string& category : categories) {
Expand Down
4 changes: 2 additions & 2 deletions src/tracing/agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Agent {
Agent();
~Agent();

TracingController* GetTracingController() { return tracing_controller_; }
TracingController* GetTracingController() { return tracing_controller_.get(); }

enum UseDefaultCategoryMode {
kUseDefaultCategories,
Expand Down Expand Up @@ -121,7 +121,7 @@ class Agent {
// These maps store the original arguments to AddClient(), by id.
std::unordered_map<int, std::multiset<std::string>> categories_;
std::unordered_map<int, std::unique_ptr<AsyncTraceWriter>> writers_;
TracingController* tracing_controller_ = nullptr;
std::unique_ptr<TracingController> tracing_controller_;

// Variables related to initializing per-event-loop properties of individual
// writers, such as libuv handles.
Expand Down

0 comments on commit 7139e97

Please sign in to comment.