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_module.cc Lines: 12 149 8.1 %
Date: 2019-02-01 22:03:38 Branches: 3 146 2.1 %

Line Branch Exec Source
1
#include "env.h"
2
#include "node_errors.h"
3
#include "node_internals.h"
4
#include "node_options.h"
5
#include "node_report.h"
6
#include "util.h"
7
8
#include "env-inl.h"
9
#include "handle_wrap.h"
10
#include "node_buffer.h"
11
#include "stream_base-inl.h"
12
#include "stream_wrap.h"
13
#include "util-inl.h"
14
15
#include <v8.h>
16
#include <atomic>
17
#include <sstream>
18
19
namespace report {
20
using node::Environment;
21
using node::FIXED_ONE_BYTE_STRING;
22
using node::PerIsolateOptions;
23
using node::Utf8Value;
24
using v8::Array;
25
using v8::Boolean;
26
using v8::Context;
27
using v8::Function;
28
using v8::FunctionCallbackInfo;
29
using v8::HandleScope;
30
using v8::Isolate;
31
using v8::Local;
32
using v8::Object;
33
using v8::String;
34
using v8::V8;
35
using v8::Value;
36
37
// Internal/static function declarations
38
void OnUncaughtException(const FunctionCallbackInfo<Value>& info);
39
static void Initialize(Local<Object> exports,
40
                       Local<Value> unused,
41
                       Local<Context> context);
42
43
// External JavaScript API for triggering a report
44
void TriggerReport(const FunctionCallbackInfo<Value>& info) {
45
  Environment* env = Environment::GetCurrent(info);
46
  Isolate* isolate = env->isolate();
47
  HandleScope scope(isolate);
48
  std::string filename;
49
  Local<String> stackstr;
50
51
  if (info.Length() == 1) {
52
    stackstr = info[0].As<String>();
53
  } else {
54
    filename = *String::Utf8Value(isolate, info[0]);
55
    stackstr = info[1].As<String>();
56
  }
57
58
  filename = TriggerNodeReport(
59
      isolate, env, "JavaScript API", __func__, filename, stackstr);
60
  // Return value is the report filename
61
  info.GetReturnValue().Set(
62
      String::NewFromUtf8(isolate, filename.c_str(), v8::NewStringType::kNormal)
63
          .ToLocalChecked());
64
}
65
66
// External JavaScript API for returning a report
67
void GetReport(const FunctionCallbackInfo<Value>& info) {
68
  Environment* env = Environment::GetCurrent(info);
69
  Isolate* isolate = env->isolate();
70
  HandleScope scope(isolate);
71
  std::ostringstream out;
72
73
  GetNodeReport(
74
      isolate, env, "JavaScript API", __func__, info[0].As<String>(), out);
75
76
  // Return value is the contents of a report as a string.
77
  info.GetReturnValue().Set(String::NewFromUtf8(isolate,
78
                                                out.str().c_str(),
79
                                                v8::NewStringType::kNormal)
80
                                .ToLocalChecked());
81
}
82
83
// Callbacks for triggering report on uncaught exception.
84
// Calls triggered from JS land.
85
void OnUncaughtException(const FunctionCallbackInfo<Value>& info) {
86
  Environment* env = Environment::GetCurrent(info);
87
  Isolate* isolate = env->isolate();
88
  HandleScope scope(isolate);
89
  std::string filename;
90
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
91
92
  // Trigger report if requested
93
  if (options->report_uncaught_exception) {
94
    TriggerNodeReport(
95
        isolate, env, "exception", __func__, filename, info[0].As<String>());
96
  }
97
}
98
99
// Signal handler for report action, called from JS land (util.js)
100
void OnUserSignal(const FunctionCallbackInfo<Value>& info) {
101
  Environment* env = Environment::GetCurrent(info);
102
  Isolate* isolate = env->isolate();
103
  CHECK(info[0]->IsString());
104
  Local<String> str = info[0].As<String>();
105
  String::Utf8Value value(isolate, str);
106
  std::string filename;
107
  TriggerNodeReport(
108
      isolate, env, *value, __func__, filename, info[0].As<String>());
109
}
110
111
// A method to sync up data elements in the JS land with its
112
// corresponding elements in the C++ world. Required because
113
// (i) the tunables are first intercepted through the CLI but
114
// later modified via APIs. (ii) the report generation events
115
// are controlled partly from C++ and partly from JS.
116
void SyncConfig(const FunctionCallbackInfo<Value>& info) {
117
  Environment* env = Environment::GetCurrent(info);
118
  Local<Context> context = env->context();
119
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
120
121
  CHECK_EQ(info.Length(), 2);
122
  Local<Object> obj;
123
  if (!info[0]->ToObject(context).ToLocal(&obj)) return;
124
  bool sync = info[1].As<Boolean>()->Value();
125
126
  // Events array
127
  Local<String> eventskey = FIXED_ONE_BYTE_STRING(env->isolate(), "events");
128
  Local<Value> events_unchecked;
129
  if (!obj->Get(context, eventskey).ToLocal(&events_unchecked)) return;
130
  Local<Array> events;
131
  if (events_unchecked->IsUndefined() || events_unchecked->IsNull()) {
132
    events_unchecked = Array::New(env->isolate(), 0);
133
    if (obj->Set(context, eventskey, events_unchecked).IsNothing()) return;
134
  }
135
  events = events_unchecked.As<Array>();
136
137
  // Signal
138
  Local<String> signalkey = env->signal_string();
139
  Local<Value> signal_unchecked;
140
  if (!obj->Get(context, signalkey).ToLocal(&signal_unchecked)) return;
141
  Local<String> signal;
142
  if (signal_unchecked->IsUndefined() || signal_unchecked->IsNull())
143
    signal_unchecked = signalkey;
144
  signal = signal_unchecked.As<String>();
145
146
  Utf8Value signalstr(env->isolate(), signal);
147
148
  // Report file
149
  Local<String> filekey = FIXED_ONE_BYTE_STRING(env->isolate(), "filename");
150
  Local<Value> file_unchecked;
151
  if (!obj->Get(context, filekey).ToLocal(&file_unchecked)) return;
152
  Local<String> file;
153
  if (file_unchecked->IsUndefined() || file_unchecked->IsNull())
154
    file_unchecked = filekey;
155
  file = file_unchecked.As<String>();
156
157
  Utf8Value filestr(env->isolate(), file);
158
159
  // Report file path
160
  Local<String> pathkey = FIXED_ONE_BYTE_STRING(env->isolate(), "path");
161
  Local<Value> path_unchecked;
162
  if (!obj->Get(context, pathkey).ToLocal(&path_unchecked)) return;
163
  Local<String> path;
164
  if (path_unchecked->IsUndefined() || path_unchecked->IsNull())
165
    path_unchecked = pathkey;
166
  path = path_unchecked.As<String>();
167
168
  Utf8Value pathstr(env->isolate(), path);
169
170
  // Report verbosity
171
  Local<String> verbosekey = FIXED_ONE_BYTE_STRING(env->isolate(), "verbose");
172
  Local<Value> verbose_unchecked;
173
  if (!obj->Get(context, verbosekey).ToLocal(&verbose_unchecked)) return;
174
  Local<Boolean> verbose;
175
  if (verbose_unchecked->IsUndefined() || verbose_unchecked->IsNull())
176
    verbose_unchecked = Boolean::New(env->isolate(), "verbose");
177
  verbose = verbose_unchecked.As<Boolean>();
178
179
  bool verb = verbose->BooleanValue(env->isolate());
180
181
  if (sync) {
182
    static const std::string e = "exception";
183
    static const std::string s = "signal";
184
    static const std::string f = "fatalerror";
185
    for (uint32_t i = 0; i < events->Length(); i++) {
186
      Local<Value> v;
187
      if (!events->Get(context, i).ToLocal(&v)) return;
188
      Local<String> elem;
189
      if (!v->ToString(context).ToLocal(&elem)) return;
190
      String::Utf8Value buf(env->isolate(), elem);
191
      if (*buf == e) {
192
        options->report_uncaught_exception = true;
193
      } else if (*buf == s) {
194
        options->report_on_signal = true;
195
      } else if (*buf == f) {
196
        options->report_on_fatalerror = true;
197
      }
198
    }
199
    CHECK_NOT_NULL(*signalstr);
200
    options->report_signal = *signalstr;
201
    CHECK_NOT_NULL(*filestr);
202
    options->report_filename = *filestr;
203
    CHECK_NOT_NULL(*pathstr);
204
    options->report_directory = *pathstr;
205
    options->report_verbose = verb;
206
  } else {
207
    int i = 0;
208
    if (options->report_uncaught_exception &&
209
        events
210
            ->Set(context,
211
                  i++,
212
                  FIXED_ONE_BYTE_STRING(env->isolate(), "exception"))
213
            .IsNothing())
214
      return;
215
    if (options->report_on_signal &&
216
        events
217
            ->Set(context, i++, FIXED_ONE_BYTE_STRING(env->isolate(), "signal"))
218
            .IsNothing())
219
      return;
220
    if (options->report_on_fatalerror &&
221
        events
222
            ->Set(
223
                context, i, FIXED_ONE_BYTE_STRING(env->isolate(), "fatalerror"))
224
            .IsNothing())
225
      return;
226
227
    Local<Value> signal_value;
228
    Local<Value> file_value;
229
    Local<Value> path_value;
230
    std::string signal = options->report_signal;
231
    if (signal.empty()) signal = "SIGUSR2";
232
    if (!node::ToV8Value(context, signal).ToLocal(&signal_value))
233
      return;
234
    if (!obj->Set(context, signalkey, signal_value).FromJust()) return;
235
236
    if (!node::ToV8Value(context, options->report_filename)
237
             .ToLocal(&file_value))
238
      return;
239
    if (!obj->Set(context, filekey, file_value).FromJust()) return;
240
241
    if (!node::ToV8Value(context, options->report_directory)
242
             .ToLocal(&path_value))
243
      return;
244
    if (!obj->Set(context, pathkey, path_value).FromJust()) return;
245
246
    if (!obj->Set(context,
247
                  verbosekey,
248
                  Boolean::New(env->isolate(), options->report_verbose))
249
             .FromJust())
250
      return;
251
  }
252
}
253
254
5
static void Initialize(Local<Object> exports,
255
                       Local<Value> unused,
256
                       Local<Context> context) {
257
5
  Environment* env = Environment::GetCurrent(context);
258
5
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
259
5
  env->SetMethod(exports, "triggerReport", TriggerReport);
260
5
  env->SetMethod(exports, "getReport", GetReport);
261
5
  env->SetMethod(exports, "onUnCaughtException", OnUncaughtException);
262
5
  env->SetMethod(exports, "onUserSignal", OnUserSignal);
263
5
  env->SetMethod(exports, "syncConfig", SyncConfig);
264
265
  // TODO(gireeshpunathil) if we are retaining this flag,
266
  // insert more verbose information at vital control flow
267
  // points. Right now, it is only this one.
268
5
  if (options->report_verbose) {
269
    std::cerr << "report: initialization complete, event flags:" << std::endl;
270
    std::cerr << "report_uncaught_exception: "
271
              << options->report_uncaught_exception << std::endl;
272
    std::cerr << "report_on_signal: " << options->report_on_signal << std::endl;
273
    std::cerr << "report_on_fatalerror: " << options->report_on_fatalerror
274
              << std::endl;
275
    std::cerr << "report_signal: " << options->report_signal << std::endl;
276
    std::cerr << "report_filename: " << options->report_filename << std::endl;
277
    std::cerr << "report_directory: " << options->report_directory << std::endl;
278
    std::cerr << "report_verbose: " << options->report_verbose << std::endl;
279
5
  }
280
5
}
281
282
}  // namespace report
283
284

656
NODE_MODULE_CONTEXT_AWARE_INTERNAL(report, report::Initialize)