Skip to content

Commit 7d1474e

Browse files
committed
core: implement runtime flag to print warn on sync
Use the --warn-on-sync flag to print a stack trace whenever a sync method is used. (e.g. fs.readFileSync()) It does not track if the warning has occurred at a specific location in the past and so will print the warning every time. This does not print the warning for the first synchronous execution of the script. Allowing all the require(), etc. statements to run that are necessary to prepare the environment.
1 parent 4e2f999 commit 7d1474e

7 files changed

+56
-1
lines changed

src/env-inl.h

+29
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ inline Environment::Environment(v8::Local<v8::Context> context,
176176
using_abort_on_uncaught_exc_(false),
177177
using_asyncwrap_(false),
178178
printed_error_(false),
179+
warn_on_sync_(false),
179180
debugger_agent_(this),
180181
context_(context->GetIsolate(), context) {
181182
// We'll be creating new objects so make sure we've entered the context.
@@ -325,6 +326,34 @@ inline void Environment::set_printed_error(bool value) {
325326
printed_error_ = value;
326327
}
327328

329+
inline void Environment::print_sync_warn() const {
330+
if (!warn_on_sync_)
331+
return;
332+
333+
v8::HandleScope handle_scope(isolate_);
334+
v8::Local<v8::StackTrace> stack = v8::StackTrace::CurrentStackTrace(
335+
isolate_, 10, v8::StackTrace::kDetailed);
336+
337+
fprintf(stderr, "WARNING: Detected use of sync API\n");
338+
for (int i = 0; i < stack->GetFrameCount() - 1; i++) {
339+
v8::Local<v8::StackFrame> sf = stack->GetFrame(i);
340+
node::Utf8Value fn_s(isolate_, sf->GetFunctionName());
341+
const char* fn;
342+
if (strcmp(*fn_s, "") == 0)
343+
fn = "(anonymous)";
344+
else
345+
fn = *fn_s;
346+
node::Utf8Value m(isolate_, sf->GetScriptName());
347+
int ln = sf->GetLineNumber();
348+
int cl = sf->GetColumn();
349+
fprintf(stderr, " at %s (%s:%i:%i)\n", fn, *m, ln, cl);
350+
}
351+
}
352+
353+
inline void Environment::set_warn_on_sync(bool value) {
354+
warn_on_sync_ = value;
355+
}
356+
328357
inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
329358
return ContainerOf(&Environment::cares_timer_handle_, handle);
330359
}

src/env.h

+4
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ class Environment {
420420
inline bool printed_error() const;
421421
inline void set_printed_error(bool value);
422422

423+
inline void print_sync_warn() const;
424+
inline void set_warn_on_sync(bool value);
425+
423426
inline void ThrowError(const char* errmsg);
424427
inline void ThrowTypeError(const char* errmsg);
425428
inline void ThrowRangeError(const char* errmsg);
@@ -506,6 +509,7 @@ class Environment {
506509
bool using_abort_on_uncaught_exc_;
507510
bool using_asyncwrap_;
508511
bool printed_error_;
512+
bool warn_on_sync_;
509513
debugger::Agent debugger_agent_;
510514

511515
HandleWrapQueue handle_wrap_queue_;

src/node.cc

+16
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ using v8::Promise;
102102
using v8::PromiseRejectMessage;
103103
using v8::PropertyCallbackInfo;
104104
using v8::SealHandleScope;
105+
using v8::StackFrame;
106+
using v8::StackTrace;
105107
using v8::String;
106108
using v8::TryCatch;
107109
using v8::Uint32;
@@ -114,6 +116,7 @@ static bool force_repl = false;
114116
static bool trace_deprecation = false;
115117
static bool throw_deprecation = false;
116118
static bool abort_on_uncaught_exception = false;
119+
static bool warn_on_sync = false;
117120
static const char* eval_string = nullptr;
118121
static unsigned int preload_module_count = 0;
119122
static const char** preload_modules = nullptr;
@@ -2834,6 +2837,13 @@ void SetupProcessObject(Environment* env,
28342837
READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
28352838
}
28362839

2840+
// --warn-on-sync
2841+
if (warn_on_sync) {
2842+
READONLY_PROPERTY(process, "warnOnSync", True(env->isolate()));
2843+
// Don't env->set_warn_on_sync(true) because it will be enabled after
2844+
// LoadEnvironment() has run.
2845+
}
2846+
28372847
size_t exec_path_len = 2 * PATH_MAX;
28382848
char* exec_path = new char[exec_path_len];
28392849
Local<String> exec_path_value;
@@ -3061,6 +3071,8 @@ static void PrintHelp() {
30613071
"function is used\n"
30623072
" --trace-deprecation show stack traces on deprecations\n"
30633073
" --v8-options print v8 command line options\n"
3074+
" --warn-on-sync print warning message when sync\n"
3075+
" function is used\n"
30643076
#if defined(NODE_HAVE_I18N_SUPPORT)
30653077
" --icu-data-dir=dir set ICU data load path to dir\n"
30663078
" (overrides NODE_ICU_DATA)\n"
@@ -3180,6 +3192,8 @@ static void ParseArgs(int* argc,
31803192
no_deprecation = true;
31813193
} else if (strcmp(arg, "--trace-deprecation") == 0) {
31823194
trace_deprecation = true;
3195+
} else if (strcmp(arg, "--warn-on-sync") == 0) {
3196+
warn_on_sync = true;
31833197
} else if (strcmp(arg, "--throw-deprecation") == 0) {
31843198
throw_deprecation = true;
31853199
} else if (strcmp(arg, "--abort-on-uncaught-exception") == 0 ||
@@ -3887,6 +3901,8 @@ static void StartNodeInstance(void* arg) {
38873901

38883902
LoadEnvironment(env);
38893903

3904+
env->set_warn_on_sync(warn_on_sync);
3905+
38903906
// Enable debugger
38913907
if (instance_data->use_debug_agent())
38923908
EnableDebug(env);

src/node_crypto.cc

+2
Original file line numberDiff line numberDiff line change
@@ -4630,6 +4630,7 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
46304630
EIO_PBKDF2,
46314631
EIO_PBKDF2After);
46324632
} else {
4633+
env->print_sync_warn();
46334634
Local<Value> argv[2];
46344635
EIO_PBKDF2(req);
46354636
EIO_PBKDF2After(req, argv);
@@ -4786,6 +4787,7 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
47864787
RandomBytesAfter);
47874788
args.GetReturnValue().Set(obj);
47884789
} else {
4790+
env->print_sync_warn();
47894791
Local<Value> argv[2];
47904792
RandomBytesWork(req->work_req());
47914793
RandomBytesCheck(req, argv);

src/node_file.cc

+1
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ struct fs_req_wrap {
280280

281281
#define SYNC_DEST_CALL(func, path, dest, ...) \
282282
fs_req_wrap req_wrap; \
283+
env->print_sync_warn(); \
283284
int err = uv_fs_ ## func(env->event_loop(), \
284285
&req_wrap.req, \
285286
__VA_ARGS__, \

src/node_zlib.cc

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class ZCtx : public AsyncWrap {
180180
ctx->chunk_size_ = out_len;
181181

182182
if (!async) {
183+
ctx->env()->print_sync_warn();
183184
// sync version
184185
Process(work_req);
185186
if (CheckError(ctx))

src/spawn_sync.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,9 @@ void SyncProcessRunner::Initialize(Handle<Object> target,
349349

350350

351351
void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
352-
SyncProcessRunner p(Environment::GetCurrent(args));
352+
Environment* env = Environment::GetCurrent(args);
353+
env->print_sync_warn();
354+
SyncProcessRunner p(env);
353355
Local<Value> result = p.Run(args[0]);
354356
args.GetReturnValue().Set(result);
355357
}

0 commit comments

Comments
 (0)