@@ -1147,42 +1147,23 @@ inline void PlatformInit() {
1147
1147
#endif // _WIN32
1148
1148
}
1149
1149
1150
- void ProcessArgv (std::vector<std::string>* args,
1151
- std::vector<std::string>* exec_args,
1152
- bool is_env) {
1150
+ int ProcessGlobalArgs (std::vector<std::string>* args,
1151
+ std::vector<std::string>* exec_args,
1152
+ std::vector<std::string>* errors,
1153
+ bool is_env) {
1153
1154
// Parse a few arguments which are specific to Node.
1154
1155
std::vector<std::string> v8_args;
1155
- std::vector<std::string> errors{};
1156
1156
1157
- {
1158
- // TODO(addaleax): The mutex here should ideally be held during the
1159
- // entire function, but that doesn't play well with the exit() calls below.
1160
- Mutex::ScopedLock lock (per_process::cli_options_mutex);
1161
- options_parser::PerProcessOptionsParser::instance.Parse (
1162
- args,
1163
- exec_args,
1164
- &v8_args,
1165
- per_process::cli_options.get (),
1166
- is_env ? kAllowedInEnvironment : kDisallowedInEnvironment ,
1167
- &errors);
1168
- }
1169
-
1170
- if (!errors.empty ()) {
1171
- for (auto const & error : errors) {
1172
- fprintf (stderr, " %s: %s\n " , args->at (0 ).c_str (), error.c_str ());
1173
- }
1174
- exit (9 );
1175
- }
1157
+ Mutex::ScopedLock lock (per_process::cli_options_mutex);
1158
+ options_parser::PerProcessOptionsParser::instance.Parse (
1159
+ args,
1160
+ exec_args,
1161
+ &v8_args,
1162
+ per_process::cli_options.get (),
1163
+ is_env ? kAllowedInEnvironment : kDisallowedInEnvironment ,
1164
+ errors);
1176
1165
1177
- if (per_process::cli_options->print_version ) {
1178
- printf (" %s\n " , NODE_VERSION);
1179
- exit (0 );
1180
- }
1181
-
1182
- if (per_process::cli_options->print_v8_help ) {
1183
- V8::SetFlagsFromString (" --help" , 6 );
1184
- exit (0 );
1185
- }
1166
+ if (!errors->empty ()) return 9 ;
1186
1167
1187
1168
for (const std::string& cve : per_process::cli_options->security_reverts )
1188
1169
Revert (cve.c_str ());
@@ -1222,19 +1203,17 @@ void ProcessArgv(std::vector<std::string>* args,
1222
1203
}
1223
1204
1224
1205
// Anything that's still in v8_argv is not a V8 or a node option.
1225
- for (size_t i = 1 ; i < v8_args_as_char_ptr.size (); i++) {
1226
- fprintf (stderr, " %s: bad option: %s\n " ,
1227
- args->at (0 ).c_str (), v8_args_as_char_ptr[i]);
1228
- }
1206
+ for (size_t i = 1 ; i < v8_args_as_char_ptr.size (); i++)
1207
+ errors->push_back (" bad option: " + std::string (v8_args_as_char_ptr[i]));
1229
1208
1230
- if (v8_args_as_char_ptr.size () > 1 ) {
1231
- exit (9 );
1232
- }
1233
- }
1209
+ if (v8_args_as_char_ptr.size () > 1 ) return 9 ;
1234
1210
1211
+ return 0 ;
1212
+ }
1235
1213
1236
- void Init (std::vector<std::string>* argv,
1237
- std::vector<std::string>* exec_argv) {
1214
+ int Init (std::vector<std::string>* argv,
1215
+ std::vector<std::string>* exec_argv,
1216
+ std::vector<std::string>* errors) {
1238
1217
// Initialize prog_start_time to get relative uptime.
1239
1218
per_process::prog_start_time = static_cast <double >(uv_now (uv_default_loop ()));
1240
1219
@@ -1295,11 +1274,13 @@ void Init(std::vector<std::string>* argv,
1295
1274
std::vector<std::string> env_argv = SplitString (" x " + node_options, ' ' );
1296
1275
env_argv[0 ] = argv->at (0 );
1297
1276
1298
- ProcessArgv (&env_argv, nullptr , true );
1277
+ const int exit_code = ProcessGlobalArgs (&env_argv, nullptr , errors, true );
1278
+ if (exit_code != 0 ) return exit_code;
1299
1279
}
1300
1280
#endif
1301
1281
1302
- ProcessArgv (argv, exec_argv, false );
1282
+ const int exit_code = ProcessGlobalArgs (argv, exec_argv, errors, false );
1283
+ if (exit_code != 0 ) return exit_code;
1303
1284
1304
1285
// Set the process.title immediately after processing argv if --title is set.
1305
1286
if (!per_process::cli_options->title .empty ())
@@ -1313,11 +1294,9 @@ void Init(std::vector<std::string>* argv,
1313
1294
// Initialize ICU.
1314
1295
// If icu_data_dir is empty here, it will load the 'minimal' data.
1315
1296
if (!i18n::InitializeICUDirectory (per_process::cli_options->icu_data_dir )) {
1316
- fprintf (stderr,
1317
- " %s: could not initialize ICU "
1318
- " (check NODE_ICU_DATA or --icu-data-dir parameters)\n " ,
1319
- argv->at (0 ).c_str ());
1320
- exit (9 );
1297
+ errors->push_back (" could not initialize ICU "
1298
+ " (check NODE_ICU_DATA or --icu-data-dir parameters)\n " );
1299
+ return 9 ;
1321
1300
}
1322
1301
per_process::metadata.versions .InitializeIntlVersions ();
1323
1302
#endif
@@ -1326,6 +1305,7 @@ void Init(std::vector<std::string>* argv,
1326
1305
// otherwise embedders using node::Init to initialize everything will not be
1327
1306
// able to set it and native modules will not load for them.
1328
1307
node_is_initialized = true ;
1308
+ return 0 ;
1329
1309
}
1330
1310
1331
1311
// TODO(addaleax): Deprecate and eventually remove this.
@@ -1335,8 +1315,25 @@ void Init(int* argc,
1335
1315
const char *** exec_argv) {
1336
1316
std::vector<std::string> argv_ (argv, argv + *argc); // NOLINT
1337
1317
std::vector<std::string> exec_argv_;
1318
+ std::vector<std::string> errors;
1319
+
1320
+ // This (approximately) duplicates some logic that has been moved to
1321
+ // node::Start(), with the difference that here we explicitly call `exit()`.
1322
+ int exit_code = Init (&argv_, &exec_argv_, &errors);
1338
1323
1339
- Init (&argv_, &exec_argv_);
1324
+ for (const std::string& error : errors)
1325
+ fprintf (stderr, " %s: %s\n " , argv_.at (0 ).c_str (), error.c_str ());
1326
+ if (exit_code != 0 ) exit (exit_code);
1327
+
1328
+ if (per_process::cli_options->print_version ) {
1329
+ printf (" %s\n " , NODE_VERSION);
1330
+ exit (0 );
1331
+ }
1332
+
1333
+ if (per_process::cli_options->print_v8_help ) {
1334
+ V8::SetFlagsFromString (" --help" , 6 ); // Doesn't return.
1335
+ UNREACHABLE ();
1336
+ }
1340
1337
1341
1338
*argc = argv_.size ();
1342
1339
*exec_argc = exec_argv_.size ();
@@ -1653,6 +1650,16 @@ inline int Start(uv_loop_t* event_loop,
1653
1650
if (isolate == nullptr )
1654
1651
return 12 ; // Signal internal error.
1655
1652
1653
+ if (per_process::cli_options->print_version ) {
1654
+ printf (" %s\n " , NODE_VERSION);
1655
+ return 0 ;
1656
+ }
1657
+
1658
+ if (per_process::cli_options->print_v8_help ) {
1659
+ V8::SetFlagsFromString (" --help" , 6 ); // Doesn't return.
1660
+ UNREACHABLE ();
1661
+ }
1662
+
1656
1663
{
1657
1664
Mutex::ScopedLock scoped_lock (per_process::main_isolate_mutex);
1658
1665
CHECK_NULL (per_process::main_isolate);
@@ -1712,8 +1719,14 @@ int Start(int argc, char** argv) {
1712
1719
1713
1720
std::vector<std::string> args (argv, argv + argc);
1714
1721
std::vector<std::string> exec_args;
1722
+ std::vector<std::string> errors;
1715
1723
// This needs to run *before* V8::Initialize().
1716
- Init (&args, &exec_args);
1724
+ {
1725
+ const int exit_code = Init (&args, &exec_args, &errors);
1726
+ for (const std::string& error : errors)
1727
+ fprintf (stderr, " %s: %s\n " , args.at (0 ).c_str (), error.c_str ());
1728
+ if (exit_code != 0 ) return exit_code;
1729
+ }
1717
1730
1718
1731
#if HAVE_OPENSSL
1719
1732
{
0 commit comments