| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1b8e8e9 commit 45eeea4
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -367,6 +367,7 @@ | |||
| 367 | 367 | 'src/base_object-inl.h', | |
| 368 | 368 | 'src/connection_wrap.h', | |
| 369 | 369 | 'src/connect_wrap.h', | |
| 370 | + 'src/debug_utils.h', | ||
| 370 | 371 | 'src/env.h', | |
| 371 | 372 | 'src/env-inl.h', | |
| 372 | 373 | 'src/handle_wrap.h', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -769,6 +769,11 @@ void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) { | |||
| 769 | 769 | Environment::GetCurrent(isolate), asyncContext.async_id); | |
| 770 | 770 | } | |
| 771 | 771 | ||
| 772 | + std::string AsyncWrap::diagnostic_name() const { | ||
| 773 | + return std::string(provider_names[provider_type()]) + | ||
| 774 | + " (" + std::to_string(static_cast<int64_t>(async_id_)) + ")"; | ||
| 775 | + } | ||
| 776 | + | ||
| 772 | 777 | } // namespace node | |
| 773 | 778 | ||
| 774 | 779 | NODE_BUILTIN_MODULE_CONTEXT_AWARE(async_wrap, node::AsyncWrap::Initialize) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -167,6 +167,7 @@ class AsyncWrap : public BaseObject { | |||
| 167 | 167 | v8::Local<v8::Value>* argv); | |
| 168 | 168 | ||
| 169 | 169 | virtual size_t self_size() const = 0; | |
| 170 | + virtual std::string diagnostic_name() const; | ||
| 170 | 171 | ||
| 171 | 172 | static void WeakCallback(const v8::WeakCallbackInfo<DestroyParam> &info); | |
| 172 | 173 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,92 @@ | |||
| 1 | + #ifndef SRC_DEBUG_UTILS_H_ | ||
| 2 | + #define SRC_DEBUG_UTILS_H_ | ||
| 3 | + | ||
| 4 | + #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | ||
| 5 | + | ||
| 6 | + #include "async_wrap.h" | ||
| 7 | + #include "env.h" | ||
| 8 | + #include <string> | ||
| 9 | + | ||
| 10 | + // Use FORCE_INLINE on functions that have a debug-category-enabled check first | ||
| 11 | + // and then ideally only a single function call following it, to maintain | ||
| 12 | + // performance for the common case (no debugging used). | ||
| 13 | + #ifdef __GNUC__ | ||
| 14 | + #define FORCE_INLINE __attribute__((always_inline)) | ||
| 15 | + #define COLD_NOINLINE __attribute__((cold, noinline)) | ||
| 16 | + #else | ||
| 17 | + #define FORCE_INLINE | ||
| 18 | + #define COLD_NOINLINE | ||
| 19 | + #endif | ||
| 20 | + | ||
| 21 | + namespace node { | ||
| 22 | + | ||
| 23 | + template <typename... Args> | ||
| 24 | + inline void FORCE_INLINE Debug(Environment* env, | ||
| 25 | + DebugCategory cat, | ||
| 26 | + const char* format, | ||
| 27 | + Args&&... args) { | ||
| 28 | + if (!UNLIKELY(env->debug_enabled(cat))) | ||
| 29 | + return; | ||
| 30 | + fprintf(stderr, format, std::forward<Args>(args)...); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + inline void FORCE_INLINE Debug(Environment* env, | ||
| 34 | + DebugCategory cat, | ||
| 35 | + const char* message) { | ||
| 36 | + if (!UNLIKELY(env->debug_enabled(cat))) | ||
| 37 | + return; | ||
| 38 | + fprintf(stderr, "%s", message); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + template <typename... Args> | ||
| 42 | + inline void Debug(Environment* env, | ||
| 43 | + DebugCategory cat, | ||
| 44 | + const std::string& format, | ||
| 45 | + Args&&... args) { | ||
| 46 | + Debug(env, cat, format.c_str(), std::forward<Args>(args)...); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + // Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that | ||
| 50 | + // the FORCE_INLINE flag on them doesn't apply to the contents of this function | ||
| 51 | + // as well. | ||
| 52 | + // We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing | ||
| 53 | + // this function for speed and it should rather focus on keeping it out of | ||
| 54 | + // hot code paths. In particular, we want to keep the string concatenating code | ||
| 55 | + // out of the function containing the original `Debug()` call. | ||
| 56 | + template <typename... Args> | ||
| 57 | + void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap, | ||
| 58 | + const char* format, | ||
| 59 | + Args&&... args) { | ||
| 60 | + Debug(async_wrap->env(), | ||
| 61 | + static_cast<DebugCategory>(async_wrap->provider_type()), | ||
| 62 | + async_wrap->diagnostic_name() + " " + format + "\n", | ||
| 63 | + std::forward<Args>(args)...); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + template <typename... Args> | ||
| 67 | + inline void FORCE_INLINE Debug(AsyncWrap* async_wrap, | ||
| 68 | + const char* format, | ||
| 69 | + Args&&... args) { | ||
| 70 | + #ifdef DEBUG | ||
| 71 | + CHECK_NOT_NULL(async_wrap); | ||
| 72 | + #endif | ||
| 73 | + DebugCategory cat = | ||
| 74 | + static_cast<DebugCategory>(async_wrap->provider_type()); | ||
| 75 | + if (!UNLIKELY(async_wrap->env()->debug_enabled(cat))) | ||
| 76 | + return; | ||
| 77 | + UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + template <typename... Args> | ||
| 81 | + inline void FORCE_INLINE Debug(AsyncWrap* async_wrap, | ||
| 82 | + const std::string& format, | ||
| 83 | + Args&&... args) { | ||
| 84 | + Debug(async_wrap, format.c_str(), std::forward<Args>(args)...); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + | ||
| 88 | + } // namespace node | ||
| 89 | + | ||
| 90 | + #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | ||
| 91 | + | ||
| 92 | + #endif // SRC_DEBUG_UTILS_H_ | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -519,6 +519,24 @@ inline void Environment::set_http2_state( | |||
| 519 | 519 | http2_state_ = std::move(buffer); | |
| 520 | 520 | } | |
| 521 | 521 | ||
| 522 | + bool Environment::debug_enabled(DebugCategory category) const { | ||
| 523 | + #ifdef DEBUG | ||
| 524 | + CHECK_GE(static_cast<int>(category), 0); | ||
| 525 | + CHECK_LT(static_cast<int>(category), | ||
| 526 | + static_cast<int>(DebugCategory::CATEGORY_COUNT)); | ||
| 527 | + #endif | ||
| 528 | + return debug_enabled_[static_cast<int>(category)]; | ||
| 529 | + } | ||
| 530 | + | ||
| 531 | + void Environment::set_debug_enabled(DebugCategory category, bool enabled) { | ||
| 532 | + #ifdef DEBUG | ||
| 533 | + CHECK_GE(static_cast<int>(category), 0); | ||
| 534 | + CHECK_LT(static_cast<int>(category), | ||
| 535 | + static_cast<int>(DebugCategory::CATEGORY_COUNT)); | ||
| 536 | + #endif | ||
| 537 | + debug_enabled_[static_cast<int>(category)] = enabled; | ||
| 538 | + } | ||
| 539 | + | ||
| 522 | 540 | inline AliasedBuffer<double, v8::Float64Array>* | |
| 523 | 541 | Environment::fs_stats_field_array() { | |
| 524 | 542 | return &fs_stats_field_array_; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -130,6 +130,10 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 130 | 130 | ||
| 131 | 131 | // By default, always abort when --abort-on-uncaught-exception was passed. | |
| 132 | 132 | should_abort_on_uncaught_toggle_[0] = 1; | |
| 133 | + | ||
| 134 | + std::string debug_cats; | ||
| 135 | + SafeGetenv("NODE_DEBUG_NATIVE", &debug_cats); | ||
| 136 | + set_debug_categories(debug_cats, true); | ||
| 133 | 137 | } | |
| 134 | 138 | ||
| 135 | 139 | Environment::~Environment() { | |
@@ -496,6 +500,28 @@ Local<Value> Environment::GetNow() { | |||
| 496 | 500 | } | |
| 497 | 501 | ||
| 498 | 502 | ||
| 503 | + void Environment::set_debug_categories(const std::string& cats, bool enabled) { | ||
| 504 | + std::string debug_categories = cats; | ||
| 505 | + while (!debug_categories.empty()) { | ||
| 506 | + std::string::size_type comma_pos = debug_categories.find(','); | ||
| 507 | + std::string wanted = ToLower(debug_categories.substr(0, comma_pos)); | ||
| 508 | + | ||
| 509 | + #define V(name) \ | ||
| 510 | + { \ | ||
| 511 | + static const std::string available_category = ToLower(#name); \ | ||
| 512 | + if (available_category.find(wanted) != std::string::npos) \ | ||
| 513 | + set_debug_enabled(DebugCategory::name, enabled); \ | ||
| 514 | + } | ||
| 515 | + | ||
| 516 | + DEBUG_CATEGORY_NAMES(V) | ||
| 517 | + | ||
| 518 | + if (comma_pos == std::string::npos) | ||
| 519 | + break; | ||
| 520 | + // Use everything after the `,` as the list for the next iteration. | ||
| 521 | + debug_categories = debug_categories.substr(comma_pos); | ||
| 522 | + } | ||
| 523 | + } | ||
| 524 | + | ||
| 499 | 525 | void CollectExceptionInfo(Environment* env, | |
| 500 | 526 | v8::Local<v8::Object> obj, | |
| 501 | 527 | int errorno, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -398,6 +398,19 @@ struct ContextInfo { | |||
| 398 | 398 | bool is_default = false; | |
| 399 | 399 | }; | |
| 400 | 400 | ||
| 401 | + // Listing the AsyncWrap provider types first enables us to cast directly | ||
| 402 | + // from a provider type to a debug category. Currently no other debug | ||
| 403 | + // categories are available. | ||
| 404 | + #define DEBUG_CATEGORY_NAMES(V) \ | ||
| 405 | + NODE_ASYNC_PROVIDER_TYPES(V) | ||
| 406 | + | ||
| 407 | + enum class DebugCategory { | ||
| 408 | + #define V(name) name, | ||
| 409 | + DEBUG_CATEGORY_NAMES(V) | ||
| 410 | + #undef V | ||
| 411 | + CATEGORY_COUNT | ||
| 412 | + }; | ||
| 413 | + | ||
| 401 | 414 | class Environment { | |
| 402 | 415 | public: | |
| 403 | 416 | class AsyncHooks { | |
@@ -654,6 +667,10 @@ class Environment { | |||
| 654 | 667 | inline http2::Http2State* http2_state() const; | |
| 655 | 668 | inline void set_http2_state(std::unique_ptr<http2::Http2State> state); | |
| 656 | 669 | ||
| 670 | + inline bool debug_enabled(DebugCategory category) const; | ||
| 671 | + inline void set_debug_enabled(DebugCategory category, bool enabled); | ||
| 672 | + void set_debug_categories(const std::string& cats, bool enabled); | ||
| 673 | + | ||
| 657 | 674 | inline AliasedBuffer<double, v8::Float64Array>* fs_stats_field_array(); | |
| 658 | 675 | ||
| 659 | 676 | // stat fields contains twice the number of entries because `fs.StatWatcher` | |
@@ -853,6 +870,8 @@ class Environment { | |||
| 853 | 870 | bool http_parser_buffer_in_use_ = false; | |
| 854 | 871 | std::unique_ptr<http2::Http2State> http2_state_; | |
| 855 | 872 | ||
| 873 | + bool debug_enabled_[static_cast<int>(DebugCategory::CATEGORY_COUNT)] = {0}; | ||
| 874 | + | ||
| 856 | 875 | AliasedBuffer<double, v8::Float64Array> fs_stats_field_array_; | |
| 857 | 876 | ||
| 858 | 877 | std::vector<std::unique_ptr<fs::FileHandleReadWrap>> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3302,6 +3302,9 @@ static void PrintHelp() { | |||
| 3302 | 3302 | "Environment variables:\n" | |
| 3303 | 3303 | "NODE_DEBUG ','-separated list of core modules\n" | |
| 3304 | 3304 | " that should print debug information\n" | |
| 3305 | + "NODE_DEBUG_NATIVE ','-separated list of C++ core debug\n" | ||
| 3306 | + " categories that should print debug\n" | ||
| 3307 | + " output\n" | ||
| 3305 | 3308 | "NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n" | |
| 3306 | 3309 | "NODE_EXTRA_CA_CERTS path to additional CA certificates\n" | |
| 3307 | 3310 | " file\n" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -293,6 +293,13 @@ char ToLower(char c) { | |||
| 293 | 293 | return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; | |
| 294 | 294 | } | |
| 295 | 295 | ||
| 296 | + std::string ToLower(const std::string& in) { | ||
| 297 | + std::string out(in.size(), 0); | ||
| 298 | + for (size_t i = 0; i < in.size(); ++i) | ||
| 299 | + out[i] = ToLower(in[i]); | ||
| 300 | + return out; | ||
| 301 | + } | ||
| 302 | + | ||
| 296 | 303 | bool StringEqualNoCase(const char* a, const char* b) { | |
| 297 | 304 | do { | |
| 298 | 305 | if (*a == '\0') | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,6 +34,7 @@ | |||
| 34 | 34 | #include <stdlib.h> | |
| 35 | 35 | #include <string.h> | |
| 36 | 36 | ||
| 37 | + #include <string> | ||
| 37 | 38 | #include <functional> // std::function | |
| 38 | 39 | ||
| 39 | 40 | namespace node { | |
@@ -250,6 +251,7 @@ inline void SwapBytes64(char* data, size_t nbytes); | |||
| 250 | 251 | ||
| 251 | 252 | // tolower() is locale-sensitive. Use ToLower() instead. | |
| 252 | 253 | inline char ToLower(char c); | |
| 254 | + inline std::string ToLower(const std::string& in); | ||
| 253 | 255 | ||
| 254 | 256 | // strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. | |
| 255 | 257 | inline bool StringEqualNoCase(const char* a, const char* b); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments