@@ -1151,42 +1151,23 @@ inline void PlatformInit() {
11511151#endif // _WIN32
11521152}
11531153
1154- void ProcessArgv (std::vector<std::string>* args,
1155- std::vector<std::string>* exec_args,
1156- bool is_env) {
1154+ int ProcessGlobalArgs (std::vector<std::string>* args,
1155+ std::vector<std::string>* exec_args,
1156+ std::vector<std::string>* errors,
1157+ bool is_env) {
11571158 // Parse a few arguments which are specific to Node.
11581159 std::vector<std::string> v8_args;
1159- std::vector<std::string> errors{};
11601160
1161- {
1162- // TODO(addaleax): The mutex here should ideally be held during the
1163- // entire function, but that doesn't play well with the exit() calls below.
1164- Mutex::ScopedLock lock (per_process::cli_options_mutex);
1165- options_parser::PerProcessOptionsParser::instance.Parse (
1166- args,
1167- exec_args,
1168- &v8_args,
1169- per_process::cli_options.get (),
1170- is_env ? kAllowedInEnvironment : kDisallowedInEnvironment ,
1171- &errors);
1172- }
1173-
1174- if (!errors.empty ()) {
1175- for (auto const & error : errors) {
1176- fprintf (stderr, " %s: %s\n " , args->at (0 ).c_str (), error.c_str ());
1177- }
1178- exit (9 );
1179- }
1161+ Mutex::ScopedLock lock (per_process::cli_options_mutex);
1162+ options_parser::PerProcessOptionsParser::instance.Parse (
1163+ args,
1164+ exec_args,
1165+ &v8_args,
1166+ per_process::cli_options.get (),
1167+ is_env ? kAllowedInEnvironment : kDisallowedInEnvironment ,
1168+ errors);
11801169
1181- if (per_process::cli_options->print_version ) {
1182- printf (" %s\n " , NODE_VERSION);
1183- exit (0 );
1184- }
1185-
1186- if (per_process::cli_options->print_v8_help ) {
1187- V8::SetFlagsFromString (" --help" , 6 );
1188- exit (0 );
1189- }
1170+ if (!errors->empty ()) return 9 ;
11901171
11911172 for (const std::string& cve : per_process::cli_options->security_reverts )
11921173 Revert (cve.c_str ());
@@ -1226,19 +1207,17 @@ void ProcessArgv(std::vector<std::string>* args,
12261207 }
12271208
12281209 // Anything that's still in v8_argv is not a V8 or a node option.
1229- for (size_t i = 1 ; i < v8_args_as_char_ptr.size (); i++) {
1230- fprintf (stderr, " %s: bad option: %s\n " ,
1231- args->at (0 ).c_str (), v8_args_as_char_ptr[i]);
1232- }
1210+ for (size_t i = 1 ; i < v8_args_as_char_ptr.size (); i++)
1211+ errors->push_back (" bad option: " + std::string (v8_args_as_char_ptr[i]));
12331212
1234- if (v8_args_as_char_ptr.size () > 1 ) {
1235- exit (9 );
1236- }
1237- }
1213+ if (v8_args_as_char_ptr.size () > 1 ) return 9 ;
12381214
1215+ return 0 ;
1216+ }
12391217
1240- void Init (std::vector<std::string>* argv,
1241- std::vector<std::string>* exec_argv) {
1218+ int Init (std::vector<std::string>* argv,
1219+ std::vector<std::string>* exec_argv,
1220+ std::vector<std::string>* errors) {
12421221 // Initialize prog_start_time to get relative uptime.
12431222 per_process::prog_start_time = static_cast <double >(uv_now (uv_default_loop ()));
12441223
@@ -1299,11 +1278,13 @@ void Init(std::vector<std::string>* argv,
12991278 std::vector<std::string> env_argv = SplitString (" x " + node_options, ' ' );
13001279 env_argv[0 ] = argv->at (0 );
13011280
1302- ProcessArgv (&env_argv, nullptr , true );
1281+ const int exit_code = ProcessGlobalArgs (&env_argv, nullptr , errors, true );
1282+ if (exit_code != 0 ) return exit_code;
13031283 }
13041284#endif
13051285
1306- ProcessArgv (argv, exec_argv, false );
1286+ const int exit_code = ProcessGlobalArgs (argv, exec_argv, errors, false );
1287+ if (exit_code != 0 ) return exit_code;
13071288
13081289 // Set the process.title immediately after processing argv if --title is set.
13091290 if (!per_process::cli_options->title .empty ())
@@ -1317,11 +1298,9 @@ void Init(std::vector<std::string>* argv,
13171298 // Initialize ICU.
13181299 // If icu_data_dir is empty here, it will load the 'minimal' data.
13191300 if (!i18n::InitializeICUDirectory (per_process::cli_options->icu_data_dir )) {
1320- fprintf (stderr,
1321- " %s: could not initialize ICU "
1322- " (check NODE_ICU_DATA or --icu-data-dir parameters)\n " ,
1323- argv->at (0 ).c_str ());
1324- exit (9 );
1301+ errors->push_back (" could not initialize ICU "
1302+ " (check NODE_ICU_DATA or --icu-data-dir parameters)\n " );
1303+ return 9 ;
13251304 }
13261305 per_process::metadata.versions .InitializeIntlVersions ();
13271306#endif
@@ -1330,6 +1309,7 @@ void Init(std::vector<std::string>* argv,
13301309 // otherwise embedders using node::Init to initialize everything will not be
13311310 // able to set it and native modules will not load for them.
13321311 node_is_initialized = true ;
1312+ return 0 ;
13331313}
13341314
13351315// TODO(addaleax): Deprecate and eventually remove this.
@@ -1339,8 +1319,25 @@ void Init(int* argc,
13391319 const char *** exec_argv) {
13401320 std::vector<std::string> argv_ (argv, argv + *argc); // NOLINT
13411321 std::vector<std::string> exec_argv_;
1322+ std::vector<std::string> errors;
1323+
1324+ // This (approximately) duplicates some logic that has been moved to
1325+ // node::Start(), with the difference that here we explicitly call `exit()`.
1326+ int exit_code = Init (&argv_, &exec_argv_, &errors);
13421327
1343- Init (&argv_, &exec_argv_);
1328+ for (const std::string& error : errors)
1329+ fprintf (stderr, " %s: %s\n " , argv_.at (0 ).c_str (), error.c_str ());
1330+ if (exit_code != 0 ) exit (exit_code);
1331+
1332+ if (per_process::cli_options->print_version ) {
1333+ printf (" %s\n " , NODE_VERSION);
1334+ exit (0 );
1335+ }
1336+
1337+ if (per_process::cli_options->print_v8_help ) {
1338+ V8::SetFlagsFromString (" --help" , 6 ); // Doesn't return.
1339+ UNREACHABLE ();
1340+ }
13441341
13451342 *argc = argv_.size ();
13461343 *exec_argc = exec_argv_.size ();
@@ -1657,6 +1654,16 @@ inline int Start(uv_loop_t* event_loop,
16571654 if (isolate == nullptr )
16581655 return 12 ; // Signal internal error.
16591656
1657+ if (per_process::cli_options->print_version ) {
1658+ printf (" %s\n " , NODE_VERSION);
1659+ return 0 ;
1660+ }
1661+
1662+ if (per_process::cli_options->print_v8_help ) {
1663+ V8::SetFlagsFromString (" --help" , 6 ); // Doesn't return.
1664+ UNREACHABLE ();
1665+ }
1666+
16601667 {
16611668 Mutex::ScopedLock scoped_lock (per_process::main_isolate_mutex);
16621669 CHECK_NULL (per_process::main_isolate);
@@ -1716,8 +1723,14 @@ int Start(int argc, char** argv) {
17161723
17171724 std::vector<std::string> args (argv, argv + argc);
17181725 std::vector<std::string> exec_args;
1726+ std::vector<std::string> errors;
17191727 // This needs to run *before* V8::Initialize().
1720- Init (&args, &exec_args);
1728+ {
1729+ const int exit_code = Init (&args, &exec_args, &errors);
1730+ for (const std::string& error : errors)
1731+ fprintf (stderr, " %s: %s\n " , args.at (0 ).c_str (), error.c_str ());
1732+ if (exit_code != 0 ) return exit_code;
1733+ }
17211734
17221735#if HAVE_OPENSSL
17231736 {
0 commit comments