Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
build: fix static initialization ordering problem in OptionsParser code
Browse files Browse the repository at this point in the history
  • Loading branch information
boingoing committed Nov 15, 2018
1 parent 2169ac4 commit f02c844
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2513,7 +2513,7 @@ void ProcessArgv(std::vector<std::string>* args,
// TODO(addaleax): The mutex here should ideally be held during the
// entire function, but that doesn't play well with the exit() calls below.
Mutex::ScopedLock lock(per_process_opts_mutex);
options_parser::PerProcessOptionsParser::instance.Parse(
options_parser::PerProcessOptionsParser::GetInstance()->Parse(
args,
exec_args,
&v8_args,
Expand Down
24 changes: 8 additions & 16 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace options_parser {
// doc/api/cli.md
// TODO(addaleax): Make that unnecessary.

DebugOptionsParser::DebugOptionsParser() {
void DebugOptionsParser::Initialize() {
#if HAVE_INSPECTOR
AddOption("--inspect-port",
"set host:port for inspector",
Expand Down Expand Up @@ -82,9 +82,7 @@ DebugOptionsParser::DebugOptionsParser() {
#endif
}

DebugOptionsParser DebugOptionsParser::instance;

EnvironmentOptionsParser::EnvironmentOptionsParser() {
void EnvironmentOptionsParser::Initialize() {
AddOption("--experimental-modules",
"experimental ES Module support and caching modules",
&EnvironmentOptions::experimental_modules,
Expand Down Expand Up @@ -191,13 +189,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
AddOption("--expose-http2", "", NoOp {}, kAllowedInEnvironment);
AddOption("--expose_http2", "", NoOp {}, kAllowedInEnvironment);

Insert(&DebugOptionsParser::instance,
Insert(DebugOptionsParser::GetInstance(),
&EnvironmentOptions::get_debug_options);
}

EnvironmentOptionsParser EnvironmentOptionsParser::instance;

PerIsolateOptionsParser::PerIsolateOptionsParser() {
void PerIsolateOptionsParser::Initialize() {
AddOption("--track-heap-objects",
"track heap object allocations for heap snapshots",
&PerIsolateOptions::track_heap_objects,
Expand All @@ -214,13 +210,11 @@ PerIsolateOptionsParser::PerIsolateOptionsParser() {
AddOption("--perf-prof", "", V8Option{}, kAllowedInEnvironment);
AddOption("--stack-trace-limit", "", V8Option{}, kAllowedInEnvironment);

Insert(&EnvironmentOptionsParser::instance,
Insert(EnvironmentOptionsParser::GetInstance(),
&PerIsolateOptions::get_per_env_options);
}

PerIsolateOptionsParser PerIsolateOptionsParser::instance;

PerProcessOptionsParser::PerProcessOptionsParser() {
void PerProcessOptionsParser::Initialize() {
AddOption("--title",
"the process title to use on startup",
&PerProcessOptions::title,
Expand Down Expand Up @@ -347,12 +341,10 @@ PerProcessOptionsParser::PerProcessOptionsParser() {
&PerProcessOptions::ttdDisableAutoTrace);
#endif

Insert(&PerIsolateOptionsParser::instance,
Insert(PerIsolateOptionsParser::GetInstance(),
&PerProcessOptions::get_per_isolate_options);
}

PerProcessOptionsParser PerProcessOptionsParser::instance;

inline std::string RemoveBrackets(const std::string& host) {
if (!host.empty() && host.front() == '[' && host.back() == ']')
return host.substr(1, host.size() - 2);
Expand Down Expand Up @@ -417,7 +409,7 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
per_process_opts->per_isolate = original_per_isolate;
});

const auto& parser = PerProcessOptionsParser::instance;
const auto& parser = *(PerProcessOptionsParser::GetInstance());

std::string filter;
if (args[0]->IsString()) filter = *node::Utf8Value(isolate, args[0]);
Expand Down
40 changes: 32 additions & 8 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,19 @@ class OptionsParser {
OptionEnvvarSettings required_env_settings,
std::vector<std::string>* const errors);


protected:
bool isInit = false;

void Ensure() {
if (!isInit) {
Initialize();
isInit = true;
}
}

virtual void Initialize() {}

private:
// We support the wide variety of different option types by remembering
// how to access them, given a certain `Options` struct.
Expand Down Expand Up @@ -363,32 +376,43 @@ class OptionsParser {
friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
};

#define OptionsParserGetInstance(type) \
static type* GetInstance() { \
static type instance; \
instance.Ensure(); \
return &instance; \
}

class DebugOptionsParser : public OptionsParser<DebugOptions> {
public:
DebugOptionsParser();
OptionsParserGetInstance(DebugOptionsParser);

static DebugOptionsParser instance;
protected:
void Initialize();
};

class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
public:
EnvironmentOptionsParser();
OptionsParserGetInstance(EnvironmentOptionsParser);

static EnvironmentOptionsParser instance;
protected:
void Initialize();
};

class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> {
public:
PerIsolateOptionsParser();
OptionsParserGetInstance(PerIsolateOptionsParser);

static PerIsolateOptionsParser instance;
protected:
void Initialize();
};

class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
public:
PerProcessOptionsParser();
OptionsParserGetInstance(PerProcessOptionsParser);

static PerProcessOptionsParser instance;
protected:
void Initialize();
};

} // namespace options_parser
Expand Down

0 comments on commit f02c844

Please sign in to comment.