From 19e77d304b2e070d69e0814961cd5431ef7fc66f Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Thu, 14 May 2015 11:46:54 -0600 Subject: [PATCH] core: implement runtime flag to pring 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 as a specific location in the past and so will print the warning every time the function is used. This does not print warnings for the first iteration of the event loop. --- src/node.cc | 31 +++++++++++++++++++++++++++++++ src/node.h | 3 +++ src/node_crypto.cc | 2 ++ src/node_file.cc | 1 + src/spawn_sync.cc | 4 +++- 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 4cafe96f445dd1..e146f899a87846 100644 --- a/src/node.cc +++ b/src/node.cc @@ -102,6 +102,8 @@ using v8::Promise; using v8::PromiseRejectMessage; using v8::PropertyCallbackInfo; using v8::SealHandleScope; +using v8::StackFrame; +using v8::StackTrace; using v8::String; using v8::TryCatch; using v8::Uint32; @@ -113,6 +115,7 @@ static bool print_eval = false; static bool force_repl = false; static bool trace_deprecation = false; static bool throw_deprecation = false; +static bool warn_on_sync = false; static bool abort_on_uncaught_exception = false; static const char* eval_string = nullptr; static unsigned int preload_module_count = 0; @@ -1492,6 +1495,27 @@ static void ReportException(Environment* env, const TryCatch& try_catch) { } +void PrintSyncWarning(Environment* env) { + if (!warn_on_sync) + return; + + Isolate* isolate = env->isolate(); + HandleScope handle_scope(isolate); + Local stack = StackTrace::CurrentStackTrace( + isolate, 10, StackTrace::kDetailed); + + fprintf(stderr, "WARNING: Detected use of sync API\n"); + for (int i = 0; i < stack->GetFrameCount() - 1; i++) { + Local sf = stack->GetFrame(i); + node::Utf8Value n(isolate, sf->GetFunctionName()); + node::Utf8Value m(isolate, sf->GetScriptName()); + int ln = sf->GetLineNumber(); + int cl = sf->GetColumn(); + fprintf(stderr, " at %s (%s:%i:%i)\n", *n, *m, ln, cl); + } +} + + // Executes a str within the current v8 context. static Local ExecuteString(Environment* env, Handle source, @@ -2834,6 +2858,11 @@ void SetupProcessObject(Environment* env, READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate())); } + // --warn-on-sync + if (warn_on_sync) { + READONLY_PROPERTY(process, "printOnSync", True(env->isolate())); + } + size_t exec_path_len = 2 * PATH_MAX; char* exec_path = new char[exec_path_len]; Local exec_path_value; @@ -3180,6 +3209,8 @@ static void ParseArgs(int* argc, no_deprecation = true; } else if (strcmp(arg, "--trace-deprecation") == 0) { trace_deprecation = true; + } else if (strcmp(arg, "--warn-on-sync") == 0) { + warn_on_sync = true; } else if (strcmp(arg, "--throw-deprecation") == 0) { throw_deprecation = true; } else if (strcmp(arg, "--abort-on-uncaught-exception") == 0 || diff --git a/src/node.h b/src/node.h index acdfe5740740ef..21b5d7c32996bc 100644 --- a/src/node.h +++ b/src/node.h @@ -335,6 +335,9 @@ NODE_DEPRECATED("Use DecodeWrite(isolate, ...)", return DecodeWrite(v8::Isolate::GetCurrent(), buf, buflen, val, encoding); }) + +void PrintSyncWarning(Environment* env); + #ifdef _WIN32 NODE_EXTERN v8::Local WinapiErrnoException( v8::Isolate* isolate, diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e49545810d3f78..3daf14859b2269 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -4630,6 +4630,7 @@ void PBKDF2(const FunctionCallbackInfo& args) { EIO_PBKDF2, EIO_PBKDF2After); } else { + PrintSyncWarning(env); Local argv[2]; EIO_PBKDF2(req); EIO_PBKDF2After(req, argv); @@ -4786,6 +4787,7 @@ void RandomBytes(const FunctionCallbackInfo& args) { RandomBytesAfter); args.GetReturnValue().Set(obj); } else { + PrintSyncWarning(env); Local argv[2]; RandomBytesWork(req->work_req()); RandomBytesCheck(req, argv); diff --git a/src/node_file.cc b/src/node_file.cc index 095710ef37e32b..c0fab7ed1ed278 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -280,6 +280,7 @@ struct fs_req_wrap { #define SYNC_DEST_CALL(func, path, dest, ...) \ fs_req_wrap req_wrap; \ + PrintSyncWarning(env); \ int err = uv_fs_ ## func(env->event_loop(), \ &req_wrap.req, \ __VA_ARGS__, \ diff --git a/src/spawn_sync.cc b/src/spawn_sync.cc index 15e4fe8b103b0d..a7c42128c76a37 100644 --- a/src/spawn_sync.cc +++ b/src/spawn_sync.cc @@ -349,7 +349,9 @@ void SyncProcessRunner::Initialize(Handle target, void SyncProcessRunner::Spawn(const FunctionCallbackInfo& args) { - SyncProcessRunner p(Environment::GetCurrent(args)); + Environment* env = Environment::GetCurrent(args); + PrintSyncWarning(env); + SyncProcessRunner p(env); Local result = p.Run(args[0]); args.GetReturnValue().Set(result); }