| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent df25900 commit 1f23c17
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1232,6 +1232,7 @@ | |||
| 1232 | 1232 | 'test/cctest/test_node_api.cc', | |
| 1233 | 1233 | 'test/cctest/test_per_process.cc', | |
| 1234 | 1234 | 'test/cctest/test_platform.cc', | |
| 1235 | + 'test/cctest/test_report.cc', | ||
| 1235 | 1236 | 'test/cctest/test_json_utils.cc', | |
| 1236 | 1237 | 'test/cctest/test_sockaddr.cc', | |
| 1237 | 1238 | 'test/cctest/test_traced_value.cc', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -75,8 +75,9 @@ | |||
| 75 | 75 | #include "v8-platform.h" // NOLINT(build/include_order) | |
| 76 | 76 | #include "node_version.h" // NODE_MODULE_VERSION | |
| 77 | 77 | ||
| 78 | - #include <memory> | ||
| 79 | 78 | #include <functional> | |
| 79 | + #include <memory> | ||
| 80 | + #include <ostream> | ||
| 80 | 81 | ||
| 81 | 82 | // We cannot use __POSIX__ in this header because that's only defined when | |
| 82 | 83 | // building Node.js. | |
@@ -531,6 +532,33 @@ NODE_EXTERN v8::MaybeLocal<v8::Value> PrepareStackTraceCallback( | |||
| 531 | 532 | v8::Local<v8::Value> exception, | |
| 532 | 533 | v8::Local<v8::Array> trace); | |
| 533 | 534 | ||
| 535 | + // Writes a diagnostic report to a file. If filename is not provided, the | ||
| 536 | + // default filename includes the date, time, PID, and a sequence number. | ||
| 537 | + // The report's JavaScript stack trace is taken from err, if present. | ||
| 538 | + // If isolate is nullptr, no information about the JavaScript environment | ||
| 539 | + // is included in the report. | ||
| 540 | + // Returns the filename of the written report. | ||
| 541 | + NODE_EXTERN std::string TriggerNodeReport(v8::Isolate* isolate, | ||
| 542 | + const char* message, | ||
| 543 | + const char* trigger, | ||
| 544 | + const std::string& filename, | ||
| 545 | + v8::Local<v8::Value> error); | ||
| 546 | + NODE_EXTERN std::string TriggerNodeReport(Environment* env, | ||
| 547 | + const char* message, | ||
| 548 | + const char* trigger, | ||
| 549 | + const std::string& filename, | ||
| 550 | + v8::Local<v8::Value> error); | ||
| 551 | + NODE_EXTERN void GetNodeReport(v8::Isolate* isolate, | ||
| 552 | + const char* message, | ||
| 553 | + const char* trigger, | ||
| 554 | + v8::Local<v8::Value> error, | ||
| 555 | + std::ostream& out); | ||
| 556 | + NODE_EXTERN void GetNodeReport(Environment* env, | ||
| 557 | + const char* message, | ||
| 558 | + const char* trigger, | ||
| 559 | + v8::Local<v8::Value> error, | ||
| 560 | + std::ostream& out); | ||
| 561 | + | ||
| 534 | 562 | // This returns the MultiIsolatePlatform used for an Environment or IsolateData | |
| 535 | 563 | // instance, if one exists. | |
| 536 | 564 | NODE_EXTERN MultiIsolatePlatform* GetMultiIsolatePlatform(Environment* env); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -449,8 +449,7 @@ static void ReportFatalException(Environment* env, | |||
| 449 | 449 | } | |
| 450 | 450 | ||
| 451 | 451 | if (env->isolate_data()->options()->report_uncaught_exception) { | |
| 452 | - report::TriggerNodeReport( | ||
| 453 | - isolate, env, report_message.c_str(), "Exception", "", error); | ||
| 452 | + TriggerNodeReport(env, report_message.c_str(), "Exception", "", error); | ||
| 454 | 453 | } | |
| 455 | 454 | ||
| 456 | 455 | if (env->options()->trace_uncaught) { | |
@@ -482,19 +481,14 @@ void OnFatalError(const char* location, const char* message) { | |||
| 482 | 481 | } | |
| 483 | 482 | ||
| 484 | 483 | Isolate* isolate = Isolate::TryGetCurrent(); | |
| 485 | - Environment* env = nullptr; | ||
| 486 | - if (isolate != nullptr) { | ||
| 487 | - env = Environment::GetCurrent(isolate); | ||
| 488 | - } | ||
| 489 | 484 | bool report_on_fatalerror; | |
| 490 | 485 | { | |
| 491 | 486 | Mutex::ScopedLock lock(node::per_process::cli_options_mutex); | |
| 492 | 487 | report_on_fatalerror = per_process::cli_options->report_on_fatalerror; | |
| 493 | 488 | } | |
| 494 | 489 | ||
| 495 | 490 | if (report_on_fatalerror) { | |
| 496 | - report::TriggerNodeReport( | ||
| 497 | - isolate, env, message, "FatalError", "", Local<Object>()); | ||
| 491 | + TriggerNodeReport(isolate, message, "FatalError", "", Local<Object>()); | ||
| 498 | 492 | } | |
| 499 | 493 | ||
| 500 | 494 | fflush(stderr); | |
@@ -512,19 +506,14 @@ void OOMErrorHandler(const char* location, bool is_heap_oom) { | |||
| 512 | 506 | } | |
| 513 | 507 | ||
| 514 | 508 | Isolate* isolate = Isolate::TryGetCurrent(); | |
| 515 | - Environment* env = nullptr; | ||
| 516 | - if (isolate != nullptr) { | ||
| 517 | - env = Environment::GetCurrent(isolate); | ||
| 518 | - } | ||
| 519 | 509 | bool report_on_fatalerror; | |
| 520 | 510 | { | |
| 521 | 511 | Mutex::ScopedLock lock(node::per_process::cli_options_mutex); | |
| 522 | 512 | report_on_fatalerror = per_process::cli_options->report_on_fatalerror; | |
| 523 | 513 | } | |
| 524 | 514 | ||
| 525 | 515 | if (report_on_fatalerror) { | |
| 526 | - report::TriggerNodeReport( | ||
| 527 | - isolate, env, message, "OOMError", "", Local<Object>()); | ||
| 516 | + TriggerNodeReport(isolate, message, "OOMError", "", Local<Object>()); | ||
| 528 | 517 | } | |
| 529 | 518 | ||
| 530 | 519 | fflush(stderr); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,8 +1,8 @@ | |||
| 1 | - #include "env-inl.h" | ||
| 2 | - #include "json_utils.h" | ||
| 3 | 1 | #include "node_report.h" | |
| 4 | 2 | #include "debug_utils-inl.h" | |
| 5 | 3 | #include "diagnosticfilename-inl.h" | |
| 4 | + #include "env-inl.h" | ||
| 5 | + #include "json_utils.h" | ||
| 6 | 6 | #include "node_internals.h" | |
| 7 | 7 | #include "node_metadata.h" | |
| 8 | 8 | #include "node_mutex.h" | |
@@ -29,8 +29,6 @@ constexpr double SEC_PER_MICROS = 1e-6; | |||
| 29 | 29 | constexpr int MAX_FRAME_COUNT = 10; | |
| 30 | 30 | ||
| 31 | 31 | namespace node { | |
| 32 | - namespace report { | ||
| 33 | - | ||
| 34 | 32 | using node::worker::Worker; | |
| 35 | 33 | using v8::Array; | |
| 36 | 34 | using v8::Context; | |
@@ -53,6 +51,7 @@ using v8::TryCatch; | |||
| 53 | 51 | using v8::V8; | |
| 54 | 52 | using v8::Value; | |
| 55 | 53 | ||
| 54 | + namespace report { | ||
| 56 | 55 | // Internal/static function declarations | |
| 57 | 56 | static void WriteNodeReport(Isolate* isolate, | |
| 58 | 57 | Environment* env, | |
@@ -83,102 +82,6 @@ static void PrintRelease(JSONWriter* writer); | |||
| 83 | 82 | static void PrintCpuInfo(JSONWriter* writer); | |
| 84 | 83 | static void PrintNetworkInterfaceInfo(JSONWriter* writer); | |
| 85 | 84 | ||
| 86 | - // External function to trigger a report, writing to file. | ||
| 87 | - std::string TriggerNodeReport(Isolate* isolate, | ||
| 88 | - Environment* env, | ||
| 89 | - const char* message, | ||
| 90 | - const char* trigger, | ||
| 91 | - const std::string& name, | ||
| 92 | - Local<Value> error) { | ||
| 93 | - std::string filename; | ||
| 94 | - | ||
| 95 | - // Determine the required report filename. In order of priority: | ||
| 96 | - // 1) supplied on API 2) configured on startup 3) default generated | ||
| 97 | - if (!name.empty()) { | ||
| 98 | - // Filename was specified as API parameter. | ||
| 99 | - filename = name; | ||
| 100 | - } else { | ||
| 101 | - std::string report_filename; | ||
| 102 | - { | ||
| 103 | - Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 104 | - report_filename = per_process::cli_options->report_filename; | ||
| 105 | - } | ||
| 106 | - if (report_filename.length() > 0) { | ||
| 107 | - // File name was supplied via start-up option. | ||
| 108 | - filename = report_filename; | ||
| 109 | - } else { | ||
| 110 | - filename = *DiagnosticFilename(env != nullptr ? env->thread_id() : 0, | ||
| 111 | - "report", "json"); | ||
| 112 | - } | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - // Open the report file stream for writing. Supports stdout/err, | ||
| 116 | - // user-specified or (default) generated name | ||
| 117 | - std::ofstream outfile; | ||
| 118 | - std::ostream* outstream; | ||
| 119 | - if (filename == "stdout") { | ||
| 120 | - outstream = &std::cout; | ||
| 121 | - } else if (filename == "stderr") { | ||
| 122 | - outstream = &std::cerr; | ||
| 123 | - } else { | ||
| 124 | - std::string report_directory; | ||
| 125 | - { | ||
| 126 | - Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 127 | - report_directory = per_process::cli_options->report_directory; | ||
| 128 | - } | ||
| 129 | - // Regular file. Append filename to directory path if one was specified | ||
| 130 | - if (report_directory.length() > 0) { | ||
| 131 | - std::string pathname = report_directory; | ||
| 132 | - pathname += kPathSeparator; | ||
| 133 | - pathname += filename; | ||
| 134 | - outfile.open(pathname, std::ios::out | std::ios::binary); | ||
| 135 | - } else { | ||
| 136 | - outfile.open(filename, std::ios::out | std::ios::binary); | ||
| 137 | - } | ||
| 138 | - // Check for errors on the file open | ||
| 139 | - if (!outfile.is_open()) { | ||
| 140 | - std::cerr << "\nFailed to open Node.js report file: " << filename; | ||
| 141 | - | ||
| 142 | - if (report_directory.length() > 0) | ||
| 143 | - std::cerr << " directory: " << report_directory; | ||
| 144 | - | ||
| 145 | - std::cerr << " (errno: " << errno << ")" << std::endl; | ||
| 146 | - return ""; | ||
| 147 | - } | ||
| 148 | - outstream = &outfile; | ||
| 149 | - std::cerr << "\nWriting Node.js report to file: " << filename; | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - bool compact; | ||
| 153 | - { | ||
| 154 | - Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 155 | - compact = per_process::cli_options->report_compact; | ||
| 156 | - } | ||
| 157 | - WriteNodeReport(isolate, env, message, trigger, filename, *outstream, | ||
| 158 | - error, compact); | ||
| 159 | - | ||
| 160 | - // Do not close stdout/stderr, only close files we opened. | ||
| 161 | - if (outfile.is_open()) { | ||
| 162 | - outfile.close(); | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - // Do not mix JSON and free-form text on stderr. | ||
| 166 | - if (filename != "stderr") { | ||
| 167 | - std::cerr << "\nNode.js report completed" << std::endl; | ||
| 168 | - } | ||
| 169 | - return filename; | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | - // External function to trigger a report, writing to a supplied stream. | ||
| 173 | - void GetNodeReport(Isolate* isolate, | ||
| 174 | - Environment* env, | ||
| 175 | - const char* message, | ||
| 176 | - const char* trigger, | ||
| 177 | - Local<Value> error, | ||
| 178 | - std::ostream& out) { | ||
| 179 | - WriteNodeReport(isolate, env, message, trigger, "", out, error, false); | ||
| 180 | - } | ||
| 181 | - | ||
| 182 | 85 | // Internal function to coordinate and write the various | |
| 183 | 86 | // sections of the report to the supplied stream | |
| 184 | 87 | static void WriteNodeReport(Isolate* isolate, | |
@@ -319,12 +222,8 @@ static void WriteNodeReport(Isolate* isolate, | |||
| 319 | 222 | expected_results += w->RequestInterrupt([&](Environment* env) { | |
| 320 | 223 | std::ostringstream os; | |
| 321 | 224 | ||
| 322 | - GetNodeReport(env->isolate(), | ||
| 323 | - env, | ||
| 324 | - "Worker thread subreport", | ||
| 325 | - trigger, | ||
| 326 | - Local<Value>(), | ||
| 327 | - os); | ||
| 225 | + GetNodeReport( | ||
| 226 | + env, "Worker thread subreport", trigger, Local<Value>(), os); | ||
| 328 | 227 | ||
| 329 | 228 | Mutex::ScopedLock lock(workers_mutex); | |
| 330 | 229 | worker_infos.emplace_back(os.str()); | |
@@ -884,4 +783,136 @@ static void PrintRelease(JSONWriter* writer) { | |||
| 884 | 783 | } | |
| 885 | 784 | ||
| 886 | 785 | } // namespace report | |
| 786 | + | ||
| 787 | + // External function to trigger a report, writing to file. | ||
| 788 | + std::string TriggerNodeReport(Isolate* isolate, | ||
| 789 | + const char* message, | ||
| 790 | + const char* trigger, | ||
| 791 | + const std::string& name, | ||
| 792 | + Local<Value> error) { | ||
| 793 | + Environment* env = nullptr; | ||
| 794 | + if (isolate != nullptr) { | ||
| 795 | + env = Environment::GetCurrent(isolate); | ||
| 796 | + } | ||
| 797 | + return TriggerNodeReport(env, message, trigger, name, error); | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + // External function to trigger a report, writing to file. | ||
| 801 | + std::string TriggerNodeReport(Environment* env, | ||
| 802 | + const char* message, | ||
| 803 | + const char* trigger, | ||
| 804 | + const std::string& name, | ||
| 805 | + Local<Value> error) { | ||
| 806 | + std::string filename; | ||
| 807 | + | ||
| 808 | + // Determine the required report filename. In order of priority: | ||
| 809 | + // 1) supplied on API 2) configured on startup 3) default generated | ||
| 810 | + if (!name.empty()) { | ||
| 811 | + // Filename was specified as API parameter. | ||
| 812 | + filename = name; | ||
| 813 | + } else { | ||
| 814 | + std::string report_filename; | ||
| 815 | + { | ||
| 816 | + Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 817 | + report_filename = per_process::cli_options->report_filename; | ||
| 818 | + } | ||
| 819 | + if (report_filename.length() > 0) { | ||
| 820 | + // File name was supplied via start-up option. | ||
| 821 | + filename = report_filename; | ||
| 822 | + } else { | ||
| 823 | + filename = *DiagnosticFilename( | ||
| 824 | + env != nullptr ? env->thread_id() : 0, "report", "json"); | ||
| 825 | + } | ||
| 826 | + } | ||
| 827 | + | ||
| 828 | + // Open the report file stream for writing. Supports stdout/err, | ||
| 829 | + // user-specified or (default) generated name | ||
| 830 | + std::ofstream outfile; | ||
| 831 | + std::ostream* outstream; | ||
| 832 | + if (filename == "stdout") { | ||
| 833 | + outstream = &std::cout; | ||
| 834 | + } else if (filename == "stderr") { | ||
| 835 | + outstream = &std::cerr; | ||
| 836 | + } else { | ||
| 837 | + std::string report_directory; | ||
| 838 | + { | ||
| 839 | + Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 840 | + report_directory = per_process::cli_options->report_directory; | ||
| 841 | + } | ||
| 842 | + // Regular file. Append filename to directory path if one was specified | ||
| 843 | + if (report_directory.length() > 0) { | ||
| 844 | + std::string pathname = report_directory; | ||
| 845 | + pathname += kPathSeparator; | ||
| 846 | + pathname += filename; | ||
| 847 | + outfile.open(pathname, std::ios::out | std::ios::binary); | ||
| 848 | + } else { | ||
| 849 | + outfile.open(filename, std::ios::out | std::ios::binary); | ||
| 850 | + } | ||
| 851 | + // Check for errors on the file open | ||
| 852 | + if (!outfile.is_open()) { | ||
| 853 | + std::cerr << "\nFailed to open Node.js report file: " << filename; | ||
| 854 | + | ||
| 855 | + if (report_directory.length() > 0) | ||
| 856 | + std::cerr << " directory: " << report_directory; | ||
| 857 | + | ||
| 858 | + std::cerr << " (errno: " << errno << ")" << std::endl; | ||
| 859 | + return ""; | ||
| 860 | + } | ||
| 861 | + outstream = &outfile; | ||
| 862 | + std::cerr << "\nWriting Node.js report to file: " << filename; | ||
| 863 | + } | ||
| 864 | + | ||
| 865 | + bool compact; | ||
| 866 | + { | ||
| 867 | + Mutex::ScopedLock lock(per_process::cli_options_mutex); | ||
| 868 | + compact = per_process::cli_options->report_compact; | ||
| 869 | + } | ||
| 870 | + | ||
| 871 | + Isolate* isolate = nullptr; | ||
| 872 | + if (env != nullptr) { | ||
| 873 | + isolate = env->isolate(); | ||
| 874 | + } | ||
| 875 | + report::WriteNodeReport( | ||
| 876 | + isolate, env, message, trigger, filename, *outstream, error, compact); | ||
| 877 | + | ||
| 878 | + // Do not close stdout/stderr, only close files we opened. | ||
| 879 | + if (outfile.is_open()) { | ||
| 880 | + outfile.close(); | ||
| 881 | + } | ||
| 882 | + | ||
| 883 | + // Do not mix JSON and free-form text on stderr. | ||
| 884 | + if (filename != "stderr") { | ||
| 885 | + std::cerr << "\nNode.js report completed" << std::endl; | ||
| 886 | + } | ||
| 887 | + return filename; | ||
| 888 | + } | ||
| 889 | + | ||
| 890 | + // External function to trigger a report, writing to a supplied stream. | ||
| 891 | + void GetNodeReport(Isolate* isolate, | ||
| 892 | + const char* message, | ||
| 893 | + const char* trigger, | ||
| 894 | + Local<Value> error, | ||
| 895 | + std::ostream& out) { | ||
| 896 | + Environment* env = nullptr; | ||
| 897 | + if (isolate != nullptr) { | ||
| 898 | + env = Environment::GetCurrent(isolate); | ||
| 899 | + } | ||
| 900 | + report::WriteNodeReport( | ||
| 901 | + isolate, env, message, trigger, "", out, error, false); | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + // External function to trigger a report, writing to a supplied stream. | ||
| 905 | + void GetNodeReport(Environment* env, | ||
| 906 | + const char* message, | ||
| 907 | + const char* trigger, | ||
| 908 | + Local<Value> error, | ||
| 909 | + std::ostream& out) { | ||
| 910 | + Isolate* isolate = nullptr; | ||
| 911 | + if (env != nullptr) { | ||
| 912 | + isolate = env->isolate(); | ||
| 913 | + } | ||
| 914 | + report::WriteNodeReport( | ||
| 915 | + isolate, env, message, trigger, "", out, error, false); | ||
| 916 | + } | ||
| 917 | + | ||
| 887 | 918 | } // namespace node | |
| Back | FazBrowse Home | New Git URL |
0 commit comments