GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_report.cc Lines: 270 271 99.6 %
Date: 2019-07-27 22:37:30 Branches: 64 88 72.7 %

Line Branch Exec Source
1
#include "env-inl.h"
2
#include "node_report.h"
3
#include "debug_utils.h"
4
#include "diagnosticfilename-inl.h"
5
#include "node_internals.h"
6
#include "node_metadata.h"
7
#include "util.h"
8
9
#ifdef _WIN32
10
#include <Windows.h>
11
#else  // !_WIN32
12
#include <sys/resource.h>
13
#include <cxxabi.h>
14
#include <dlfcn.h>
15
#endif
16
17
#include <cstring>
18
#include <ctime>
19
#include <cwctype>
20
#include <fstream>
21
#include <iomanip>
22
23
#ifndef _WIN32
24
extern char** environ;
25
#endif
26
27
constexpr int NODE_REPORT_VERSION = 1;
28
constexpr int NANOS_PER_SEC = 1000 * 1000 * 1000;
29
constexpr double SEC_PER_MICROS = 1e-6;
30
31
namespace report {
32
using node::arraysize;
33
using node::DiagnosticFilename;
34
using node::Environment;
35
using node::Mutex;
36
using node::NativeSymbolDebuggingContext;
37
using node::PerIsolateOptions;
38
using node::TIME_TYPE;
39
using v8::HeapSpaceStatistics;
40
using v8::HeapStatistics;
41
using v8::Isolate;
42
using v8::Local;
43
using v8::Number;
44
using v8::StackTrace;
45
using v8::String;
46
using v8::V8;
47
using v8::Value;
48
49
// Internal/static function declarations
50
static void WriteNodeReport(Isolate* isolate,
51
                            Environment* env,
52
                            const char* message,
53
                            const char* trigger,
54
                            const std::string& filename,
55
                            std::ostream& out,
56
                            Local<String> stackstr);
57
static void PrintVersionInformation(JSONWriter* writer);
58
static void PrintJavaScriptStack(JSONWriter* writer,
59
                                 Isolate* isolate,
60
                                 Local<String> stackstr,
61
                                 const char* trigger);
62
static void PrintNativeStack(JSONWriter* writer);
63
static void PrintResourceUsage(JSONWriter* writer);
64
static void PrintGCStatistics(JSONWriter* writer, Isolate* isolate);
65
static void PrintSystemInformation(JSONWriter* writer);
66
static void PrintLoadedLibraries(JSONWriter* writer);
67
static void PrintComponentVersions(JSONWriter* writer);
68
static void PrintRelease(JSONWriter* writer);
69
static void PrintCpuInfo(JSONWriter* writer);
70
71
// External function to trigger a report, writing to file.
72
// The 'name' parameter is in/out: an input filename is used
73
// if supplied, and the actual filename is returned.
74
11
std::string TriggerNodeReport(Isolate* isolate,
75
                              Environment* env,
76
                              const char* message,
77
                              const char* trigger,
78
                              const std::string& name,
79
                              Local<String> stackstr) {
80
11
  std::string filename;
81
22
  std::shared_ptr<PerIsolateOptions> options;
82
11
  if (env != nullptr) options = env->isolate_data()->options();
83
84
  // Determine the required report filename. In order of priority:
85
  //   1) supplied on API 2) configured on startup 3) default generated
86
11
  if (!name.empty()) {
87
    // Filename was specified as API parameter.
88
4
    filename = name;
89

7
  } else if (env != nullptr && options->report_filename.length() > 0) {
90
    // File name was supplied via start-up option.
91
1
    filename = options->report_filename;
92
  } else {
93
12
    filename = *DiagnosticFilename(env != nullptr ? env->thread_id() : 0,
94
6
                                   "report", "json");
95
  }
96
97
  // Open the report file stream for writing. Supports stdout/err,
98
  // user-specified or (default) generated name
99
22
  std::ofstream outfile;
100
  std::ostream* outstream;
101
11
  if (filename == "stdout") {
102
1
    outstream = &std::cout;
103
10
  } else if (filename == "stderr") {
104
1
    outstream = &std::cerr;
105
  } else {
106
    // Regular file. Append filename to directory path if one was specified
107

9
    if (env != nullptr && options->report_directory.length() > 0) {
108
9
      std::string pathname = options->report_directory;
109
9
      pathname += node::kPathSeparator;
110
9
      pathname += filename;
111
9
      outfile.open(pathname, std::ios::out | std::ios::binary);
112
    } else {
113
      outfile.open(filename, std::ios::out | std::ios::binary);
114
    }
115
    // Check for errors on the file open
116
9
    if (!outfile.is_open()) {
117
1
      std::cerr << std::endl
118
1
                << "Failed to open Node.js report file: " << filename;
119
120

1
      if (env != nullptr && options->report_directory.length() > 0)
121
1
        std::cerr << " directory: " << options->report_directory;
122
123
1
      std::cerr << " (errno: " << errno << ")" << std::endl;
124
1
      return "";
125
    }
126
8
    outstream = &outfile;
127
8
    std::cerr << std::endl << "Writing Node.js report to file: " << filename;
128
  }
129
130
  WriteNodeReport(isolate, env, message, trigger, filename, *outstream,
131
10
                  stackstr);
132
133
  // Do not close stdout/stderr, only close files we opened.
134
10
  if (outfile.is_open()) {
135
8
    outfile.close();
136
  }
137
138
10
  std::cerr << std::endl << "Node.js report completed" << std::endl;
139
21
  return filename;
140
}
141
142
// External function to trigger a report, writing to a supplied stream.
143
5
void GetNodeReport(Isolate* isolate,
144
                   Environment* env,
145
                   const char* message,
146
                   const char* trigger,
147
                   Local<String> stackstr,
148
                   std::ostream& out) {
149
5
  WriteNodeReport(isolate, env, message, trigger, "", out, stackstr);
150
5
}
151
152
// Internal function to coordinate and write the various
153
// sections of the report to the supplied stream
154
15
static void WriteNodeReport(Isolate* isolate,
155
                            Environment* env,
156
                            const char* message,
157
                            const char* trigger,
158
                            const std::string& filename,
159
                            std::ostream& out,
160
                            Local<String> stackstr) {
161
  // Obtain the current time and the pid.
162
  TIME_TYPE tm_struct;
163
15
  DiagnosticFilename::LocalTime(&tm_struct);
164
15
  uv_pid_t pid = uv_os_getpid();
165
166
  // Save formatting for output stream.
167
15
  std::ios old_state(nullptr);
168
15
  old_state.copyfmt(out);
169
170
  // File stream opened OK, now start printing the report content:
171
  // the title and header information (event, filename, timestamp and pid)
172
173
15
  JSONWriter writer(out);
174
15
  writer.json_start();
175
15
  writer.json_objectstart("header");
176
15
  writer.json_keyvalue("reportVersion", NODE_REPORT_VERSION);
177
15
  writer.json_keyvalue("event", message);
178
15
  writer.json_keyvalue("trigger", trigger);
179
15
  if (!filename.empty())
180
10
    writer.json_keyvalue("filename", filename);
181
  else
182
5
    writer.json_keyvalue("filename", JSONWriter::Null{});
183
184
  // Report dump event and module load date/time stamps
185
  char timebuf[64];
186
#ifdef _WIN32
187
  snprintf(timebuf,
188
           sizeof(timebuf),
189
           "%4d-%02d-%02dT%02d:%02d:%02dZ",
190
           tm_struct.wYear,
191
           tm_struct.wMonth,
192
           tm_struct.wDay,
193
           tm_struct.wHour,
194
           tm_struct.wMinute,
195
           tm_struct.wSecond);
196
  writer.json_keyvalue("dumpEventTime", timebuf);
197
#else  // UNIX, OSX
198
  snprintf(timebuf,
199
           sizeof(timebuf),
200
           "%4d-%02d-%02dT%02d:%02d:%02dZ",
201
           tm_struct.tm_year + 1900,
202
           tm_struct.tm_mon + 1,
203
           tm_struct.tm_mday,
204
           tm_struct.tm_hour,
205
           tm_struct.tm_min,
206
15
           tm_struct.tm_sec);
207
15
  writer.json_keyvalue("dumpEventTime", timebuf);
208
#endif
209
210
  uv_timeval64_t ts;
211
15
  if (uv_gettimeofday(&ts) == 0) {
212
    writer.json_keyvalue("dumpEventTimeStamp",
213
15
                         std::to_string(ts.tv_sec * 1000 + ts.tv_usec / 1000));
214
  }
215
216
  // Report native process ID
217
15
  writer.json_keyvalue("processId", pid);
218
219
  {
220
    // Report the process cwd.
221
    char buf[PATH_MAX_BYTES];
222
15
    size_t cwd_size = sizeof(buf);
223
15
    if (uv_cwd(buf, &cwd_size) == 0)
224
15
      writer.json_keyvalue("cwd", buf);
225
  }
226
227
  // Report out the command line.
228
15
  if (!node::per_process::cli_options->cmdline.empty()) {
229
15
    writer.json_arraystart("commandLine");
230
65
    for (const std::string& arg : node::per_process::cli_options->cmdline) {
231
50
      writer.json_element(arg);
232
    }
233
15
    writer.json_arrayend();
234
  }
235
236
  // Report Node.js and OS version information
237
15
  PrintVersionInformation(&writer);
238
15
  writer.json_objectend();
239
240
  // Report summary JavaScript stack backtrace
241
15
  PrintJavaScriptStack(&writer, isolate, stackstr, trigger);
242
243
  // Report native stack backtrace
244
15
  PrintNativeStack(&writer);
245
246
  // Report V8 Heap and Garbage Collector information
247
15
  PrintGCStatistics(&writer, isolate);
248
249
  // Report OS and current thread resource usage
250
15
  PrintResourceUsage(&writer);
251
252
15
  writer.json_arraystart("libuv");
253
15
  if (env != nullptr) {
254
15
    uv_walk(env->event_loop(), WalkHandle, static_cast<void*>(&writer));
255
256
15
    writer.json_start();
257
15
    writer.json_keyvalue("type", "loop");
258
    writer.json_keyvalue("is_active",
259
15
        static_cast<bool>(uv_loop_alive(env->event_loop())));
260
    writer.json_keyvalue("address",
261
15
        ValueToHexString(reinterpret_cast<int64_t>(env->event_loop())));
262
15
    writer.json_end();
263
  }
264
265
15
  writer.json_arrayend();
266
267
  // Report operating system information
268
15
  PrintSystemInformation(&writer);
269
270
15
  writer.json_objectend();
271
272
  // Restore output stream formatting.
273
15
  out.copyfmt(old_state);
274
15
}
275
276
// Report Node.js version, OS version and machine information.
277
15
static void PrintVersionInformation(JSONWriter* writer) {
278
15
  std::ostringstream buf;
279
  // Report Node version
280
15
  buf << "v" << NODE_VERSION_STRING;
281
15
  writer->json_keyvalue("nodejsVersion", buf.str());
282
15
  buf.str("");
283
284
#ifndef _WIN32
285
  // Report compiler and runtime glibc versions where possible.
286
  const char* (*libc_version)();
287
  *(reinterpret_cast<void**>(&libc_version)) =
288
15
      dlsym(RTLD_DEFAULT, "gnu_get_libc_version");
289
15
  if (libc_version != nullptr)
290
15
    writer->json_keyvalue("glibcVersionRuntime", (*libc_version)());
291
#endif /* _WIN32 */
292
293
#ifdef __GLIBC__
294
15
  buf << __GLIBC__ << "." << __GLIBC_MINOR__;
295
15
  writer->json_keyvalue("glibcVersionCompiler", buf.str());
296
15
  buf.str("");
297
#endif
298
299
  // Report Process word size
300
15
  writer->json_keyvalue("wordSize", sizeof(void*) * 8);
301
15
  writer->json_keyvalue("arch", node::per_process::metadata.arch);
302
15
  writer->json_keyvalue("platform", node::per_process::metadata.platform);
303
304
  // Report deps component versions
305
15
  PrintComponentVersions(writer);
306
307
  // Report release metadata.
308
15
  PrintRelease(writer);
309
310
  // Report operating system and machine information
311
  uv_utsname_t os_info;
312
313
15
  if (uv_os_uname(&os_info) == 0) {
314
15
    writer->json_keyvalue("osName", os_info.sysname);
315
15
    writer->json_keyvalue("osRelease", os_info.release);
316
15
    writer->json_keyvalue("osVersion", os_info.version);
317
15
    writer->json_keyvalue("osMachine", os_info.machine);
318
  }
319
320
15
  PrintCpuInfo(writer);
321
322
  char host[UV_MAXHOSTNAMESIZE];
323
15
  size_t host_size = sizeof(host);
324
325
15
  if (uv_os_gethostname(host, &host_size) == 0)
326
15
    writer->json_keyvalue("host", host);
327
15
}
328
329
// Report CPU info
330
15
static void PrintCpuInfo(JSONWriter* writer) {
331
  uv_cpu_info_t* cpu_info;
332
  int count;
333
15
  if (uv_cpu_info(&cpu_info, &count) == 0) {
334
15
    writer->json_arraystart("cpus");
335
135
    for (int i = 0; i < count; i++) {
336
120
      writer->json_start();
337
120
      writer->json_keyvalue("model", cpu_info[i].model);
338
120
      writer->json_keyvalue("speed", cpu_info[i].speed);
339
120
      writer->json_keyvalue("user", cpu_info[i].cpu_times.user);
340
120
      writer->json_keyvalue("nice", cpu_info[i].cpu_times.nice);
341
120
      writer->json_keyvalue("sys", cpu_info[i].cpu_times.sys);
342
120
      writer->json_keyvalue("idle", cpu_info[i].cpu_times.idle);
343
120
      writer->json_keyvalue("irq", cpu_info[i].cpu_times.irq);
344
120
      writer->json_end();
345
    }
346
15
    writer->json_arrayend();
347
15
    uv_free_cpu_info(cpu_info, count);
348
  }
349
15
}
350
351
// Report the JavaScript stack.
352
15
static void PrintJavaScriptStack(JSONWriter* writer,
353
                                 Isolate* isolate,
354
                                 Local<String> stackstr,
355
                                 const char* trigger) {
356
15
  writer->json_objectstart("javascriptStack");
357
358
15
  std::string ss;
359

30
  if ((!strcmp(trigger, "FatalError")) ||
360
15
      (!strcmp(trigger, "Signal"))) {
361
1
    ss = "No stack.\nUnavailable.\n";
362
  } else {
363
14
    String::Utf8Value sv(isolate, stackstr);
364
14
    ss = std::string(*sv, sv.length());
365
  }
366
15
  int line = ss.find('\n');
367
15
  if (line == -1) {
368
2
    writer->json_keyvalue("message", ss);
369
  } else {
370
13
    std::string l = ss.substr(0, line);
371
13
    writer->json_keyvalue("message", l);
372
13
    writer->json_arraystart("stack");
373
13
    ss = ss.substr(line + 1);
374
13
    line = ss.find('\n');
375
104
    while (line != -1) {
376
78
      l = ss.substr(0, line);
377
386
      l.erase(l.begin(), std::find_if(l.begin(), l.end(), [](int ch) {
378
386
                return !std::iswspace(ch);
379
464
              }));
380
78
      writer->json_element(l);
381
78
      ss = ss.substr(line + 1);
382
78
      line = ss.find('\n');
383
    }
384
13
    writer->json_arrayend();
385
  }
386
15
  writer->json_objectend();
387
15
}
388
389
// Report a native stack backtrace
390
15
static void PrintNativeStack(JSONWriter* writer) {
391
15
  auto sym_ctx = NativeSymbolDebuggingContext::New();
392
  void* frames[256];
393
15
  const int size = sym_ctx->GetStackTrace(frames, arraysize(frames));
394
15
  writer->json_arraystart("nativeStack");
395
  int i;
396
135
  for (i = 1; i < size; i++) {
397
120
    void* frame = frames[i];
398
120
    writer->json_start();
399
    writer->json_keyvalue("pc",
400
120
                          ValueToHexString(reinterpret_cast<uintptr_t>(frame)));
401
120
    writer->json_keyvalue("symbol", sym_ctx->LookupSymbol(frame).Display());
402
120
    writer->json_end();
403
  }
404
15
  writer->json_arrayend();
405
15
}
406
407
// Report V8 JavaScript heap information.
408
// This uses the existing V8 HeapStatistics and HeapSpaceStatistics APIs.
409
// The isolate->GetGCStatistics(&heap_stats) internal V8 API could potentially
410
// provide some more useful information - the GC history and the handle counts
411
15
static void PrintGCStatistics(JSONWriter* writer, Isolate* isolate) {
412
15
  HeapStatistics v8_heap_stats;
413
15
  isolate->GetHeapStatistics(&v8_heap_stats);
414
15
  HeapSpaceStatistics v8_heap_space_stats;
415
416
15
  writer->json_objectstart("javascriptHeap");
417
15
  writer->json_keyvalue("totalMemory", v8_heap_stats.total_heap_size());
418
  writer->json_keyvalue("totalCommittedMemory",
419
15
                        v8_heap_stats.total_physical_size());
420
15
  writer->json_keyvalue("usedMemory", v8_heap_stats.used_heap_size());
421
  writer->json_keyvalue("availableMemory",
422
15
                        v8_heap_stats.total_available_size());
423
15
  writer->json_keyvalue("memoryLimit", v8_heap_stats.heap_size_limit());
424
425
15
  writer->json_objectstart("heapSpaces");
426
  // Loop through heap spaces
427
135
  for (size_t i = 0; i < isolate->NumberOfHeapSpaces(); i++) {
428
120
    isolate->GetHeapSpaceStatistics(&v8_heap_space_stats, i);
429
120
    writer->json_objectstart(v8_heap_space_stats.space_name());
430
120
    writer->json_keyvalue("memorySize", v8_heap_space_stats.space_size());
431
    writer->json_keyvalue(
432
        "committedMemory",
433
120
        v8_heap_space_stats.physical_space_size());
434
    writer->json_keyvalue(
435
        "capacity",
436
240
        v8_heap_space_stats.space_used_size() +
437
240
            v8_heap_space_stats.space_available_size());
438
120
    writer->json_keyvalue("used", v8_heap_space_stats.space_used_size());
439
    writer->json_keyvalue(
440
120
        "available", v8_heap_space_stats.space_available_size());
441
120
    writer->json_objectend();
442
  }
443
444
15
  writer->json_objectend();
445
15
  writer->json_objectend();
446
15
}
447
448
15
static void PrintResourceUsage(JSONWriter* writer) {
449
  // Get process uptime in seconds
450
  uint64_t uptime =
451
15
      (uv_hrtime() - node::per_process::node_start_time) / (NANOS_PER_SEC);
452
15
  if (uptime == 0) uptime = 1;  // avoid division by zero.
453
454
  // Process and current thread usage statistics
455
  uv_rusage_t rusage;
456
15
  writer->json_objectstart("resourceUsage");
457
15
  if (uv_getrusage(&rusage) == 0) {
458
    double user_cpu =
459
15
        rusage.ru_utime.tv_sec + SEC_PER_MICROS * rusage.ru_utime.tv_usec;
460
    double kernel_cpu =
461
15
        rusage.ru_stime.tv_sec + SEC_PER_MICROS * rusage.ru_stime.tv_usec;
462
15
    writer->json_keyvalue("userCpuSeconds", user_cpu);
463
15
    writer->json_keyvalue("kernelCpuSeconds", kernel_cpu);
464
15
    double cpu_abs = user_cpu + kernel_cpu;
465
15
    double cpu_percentage = (cpu_abs / uptime) * 100.0;
466
15
    writer->json_keyvalue("cpuConsumptionPercent", cpu_percentage);
467
15
    writer->json_keyvalue("maxRss", rusage.ru_maxrss * 1024);
468
15
    writer->json_objectstart("pageFaults");
469
15
    writer->json_keyvalue("IORequired", rusage.ru_majflt);
470
15
    writer->json_keyvalue("IONotRequired", rusage.ru_minflt);
471
15
    writer->json_objectend();
472
15
    writer->json_objectstart("fsActivity");
473
15
    writer->json_keyvalue("reads", rusage.ru_inblock);
474
15
    writer->json_keyvalue("writes", rusage.ru_oublock);
475
15
    writer->json_objectend();
476
  }
477
15
  writer->json_objectend();
478
#ifdef RUSAGE_THREAD
479
  struct rusage stats;
480
15
  if (getrusage(RUSAGE_THREAD, &stats) == 0) {
481
15
    writer->json_objectstart("uvthreadResourceUsage");
482
    double user_cpu =
483
15
        stats.ru_utime.tv_sec + SEC_PER_MICROS * stats.ru_utime.tv_usec;
484
    double kernel_cpu =
485
15
        stats.ru_stime.tv_sec + SEC_PER_MICROS * stats.ru_stime.tv_usec;
486
15
    writer->json_keyvalue("userCpuSeconds", user_cpu);
487
15
    writer->json_keyvalue("kernelCpuSeconds", kernel_cpu);
488
15
    double cpu_abs = user_cpu + kernel_cpu;
489
15
    double cpu_percentage = (cpu_abs / uptime) * 100.0;
490
15
    writer->json_keyvalue("cpuConsumptionPercent", cpu_percentage);
491
15
    writer->json_objectstart("fsActivity");
492
15
    writer->json_keyvalue("reads", stats.ru_inblock);
493
15
    writer->json_keyvalue("writes", stats.ru_oublock);
494
15
    writer->json_objectend();
495
15
    writer->json_objectend();
496
  }
497
#endif
498
15
}
499
500
// Report operating system information.
501
15
static void PrintSystemInformation(JSONWriter* writer) {
502
#ifndef _WIN32
503
  static struct {
504
    const char* description;
505
    int id;
506
  } rlimit_strings[] = {
507
    {"core_file_size_blocks", RLIMIT_CORE},
508
    {"data_seg_size_kbytes", RLIMIT_DATA},
509
    {"file_size_blocks", RLIMIT_FSIZE},
510
#if !(defined(_AIX) || defined(__sun))
511
    {"max_locked_memory_bytes", RLIMIT_MEMLOCK},
512
#endif
513
#ifndef __sun
514
    {"max_memory_size_kbytes", RLIMIT_RSS},
515
#endif
516
    {"open_files", RLIMIT_NOFILE},
517
    {"stack_size_bytes", RLIMIT_STACK},
518
    {"cpu_time_seconds", RLIMIT_CPU},
519
#ifndef __sun
520
    {"max_user_processes", RLIMIT_NPROC},
521
#endif
522
    {"virtual_memory_kbytes", RLIMIT_AS}
523
  };
524
#endif  // _WIN32
525
15
  writer->json_objectstart("environmentVariables");
526
15
  Mutex::ScopedLock lock(node::per_process::env_var_mutex);
527
#ifdef _WIN32
528
  LPWSTR lpszVariable;
529
  LPWCH lpvEnv;
530
531
  // Get pointer to the environment block
532
  lpvEnv = GetEnvironmentStringsW();
533
  if (lpvEnv != nullptr) {
534
    // Variable strings are separated by null bytes,
535
    // and the block is terminated by a null byte.
536
    lpszVariable = reinterpret_cast<LPWSTR>(lpvEnv);
537
    while (*lpszVariable) {
538
      DWORD size = WideCharToMultiByte(
539
          CP_UTF8, 0, lpszVariable, -1, nullptr, 0, nullptr, nullptr);
540
      char* str = new char[size];
541
      WideCharToMultiByte(
542
          CP_UTF8, 0, lpszVariable, -1, str, size, nullptr, nullptr);
543
      std::string env(str);
544
      int sep = env.rfind('=');
545
      std::string key = env.substr(0, sep);
546
      std::string value = env.substr(sep + 1);
547
      writer->json_keyvalue(key, value);
548
      lpszVariable += lstrlenW(lpszVariable) + 1;
549
    }
550
    FreeEnvironmentStringsW(lpvEnv);
551
  }
552
  writer->json_objectend();
553
#else
554
30
  std::string pair;
555
960
  for (char** env = environ; *env != nullptr; ++env) {
556
945
    std::string pair(*env);
557
945
    int separator = pair.find('=');
558
1890
    std::string key = pair.substr(0, separator);
559
1890
    std::string str = pair.substr(separator + 1);
560
945
    writer->json_keyvalue(key, str);
561
945
  }
562
15
  writer->json_objectend();
563
564
15
  writer->json_objectstart("userLimits");
565
  struct rlimit limit;
566
30
  std::string soft, hard;
567
568
165
  for (size_t i = 0; i < arraysize(rlimit_strings); i++) {
569
150
    if (getrlimit(rlimit_strings[i].id, &limit) == 0) {
570
150
      writer->json_objectstart(rlimit_strings[i].description);
571
572
150
      if (limit.rlim_cur == RLIM_INFINITY)
573
90
        writer->json_keyvalue("soft", "unlimited");
574
      else
575
60
        writer->json_keyvalue("soft", limit.rlim_cur);
576
577
150
      if (limit.rlim_max == RLIM_INFINITY)
578
105
        writer->json_keyvalue("hard", "unlimited");
579
      else
580
45
        writer->json_keyvalue("hard", limit.rlim_max);
581
582
150
      writer->json_objectend();
583
    }
584
  }
585
15
  writer->json_objectend();
586
#endif
587
588
30
  PrintLoadedLibraries(writer);
589
15
}
590
591
// Report a list of loaded native libraries.
592
15
static void PrintLoadedLibraries(JSONWriter* writer) {
593
15
  writer->json_arraystart("sharedObjects");
594
  std::vector<std::string> modules =
595
15
      NativeSymbolDebuggingContext::GetLoadedLibraries();
596
15
  for (auto const& module_name : modules) writer->json_element(module_name);
597
15
  writer->json_arrayend();
598
15
}
599
600
// Obtain and report the node and subcomponent version strings.
601
15
static void PrintComponentVersions(JSONWriter* writer) {
602
15
  std::stringstream buf;
603
604
15
  writer->json_objectstart("componentVersions");
605
606
#define V(key)                                                                 \
607
  writer->json_keyvalue(#key, node::per_process::metadata.versions.key);
608
15
  NODE_VERSIONS_KEYS(V)
609
#undef V
610
611
15
  writer->json_objectend();
612
15
}
613
614
// Report runtime release information.
615
15
static void PrintRelease(JSONWriter* writer) {
616
15
  writer->json_objectstart("release");
617
15
  writer->json_keyvalue("name", node::per_process::metadata.release.name);
618
#if NODE_VERSION_IS_LTS
619
  writer->json_keyvalue("lts", node::per_process::metadata.release.lts);
620
#endif
621
622
#ifdef NODE_HAS_RELEASE_URLS
623
  writer->json_keyvalue("headersUrl",
624
                        node::per_process::metadata.release.headers_url);
625
  writer->json_keyvalue("sourceUrl",
626
                        node::per_process::metadata.release.source_url);
627
#ifdef _WIN32
628
  writer->json_keyvalue("libUrl", node::per_process::metadata.release.lib_url);
629
#endif  // _WIN32
630
#endif  // NODE_HAS_RELEASE_URLS
631
632
15
  writer->json_objectend();
633
15
}
634
635

14496
}  // namespace report