Skip to content

Commit 4c6193f

Browse files
legendecasdanielleadams
authored andcommitted
report: generates report on threads with no isolates
PR-URL: #38994 Reviewed-By: Gireesh Punathil <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 4174f13 commit 4c6193f

File tree

4 files changed

+89
-49
lines changed

4 files changed

+89
-49
lines changed

‎src/node_errors.cc‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,13 +425,10 @@ void OnFatalError(const char* location, const char* message){
425425
}
426426

427427
Isolate* isolate = Isolate::GetCurrent();
428-
// TODO(legendecas): investigate failures on triggering node-report with
429-
// nullptr isolates.
430-
if (isolate == nullptr){
431-
fflush(stderr);
432-
ABORT();
428+
Environment* env = nullptr;
429+
if (isolate != nullptr){
430+
env = Environment::GetCurrent(isolate);
433431
}
434-
Environment* env = Environment::GetCurrent(isolate);
435432
bool report_on_fatalerror;
436433
{
437434
Mutex::ScopedLock lock(node::per_process::cli_options_mutex);

‎src/node_report.cc‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,20 +272,22 @@ static void WriteNodeReport(Isolate* isolate,
272272
PrintVersionInformation(&writer);
273273
writer.json_objectend();
274274

275-
writer.json_objectstart("javascriptStack");
276-
// Report summary JavaScript error stack backtrace
277-
PrintJavaScriptErrorStack(&writer, isolate, error, trigger);
275+
if (isolate != nullptr){
276+
writer.json_objectstart("javascriptStack");
277+
// Report summary JavaScript error stack backtrace
278+
PrintJavaScriptErrorStack(&writer, isolate, error, trigger);
278279

279-
// Report summary JavaScript error properties backtrace
280-
PrintJavaScriptErrorProperties(&writer, isolate, error);
281-
writer.json_objectend(); // the end of 'javascriptStack'
280+
// Report summary JavaScript error properties backtrace
281+
PrintJavaScriptErrorProperties(&writer, isolate, error);
282+
writer.json_objectend(); // the end of 'javascriptStack'
283+
284+
// Report V8 Heap and Garbage Collector information
285+
PrintGCStatistics(&writer, isolate);
286+
}
282287

283288
// Report native stack backtrace
284289
PrintNativeStack(&writer);
285290

286-
// Report V8 Heap and Garbage Collector information
287-
PrintGCStatistics(&writer, isolate);
288-
289291
// Report OS and current thread resource usage
290292
PrintResourceUsage(&writer);
291293

‎test/common/report.js‎

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,20 @@ function validateContent(report, fields = []){
5454

5555
function_validateContent(report,fields=[]){
5656
constisWindows=process.platform==='win32';
57+
constisJavaScriptThreadReport=report.javascriptStack!=null;
5758

5859
// Verify that all sections are present as own properties of the report.
59-
constsections=['header','javascriptStack','nativeStack',
60-
'javascriptHeap','libuv','environmentVariables',
60+
constsections=['header','nativeStack','libuv','environmentVariables',
6161
'sharedObjects','resourceUsage','workers'];
6262
if(!isWindows)
6363
sections.push('userLimits');
6464

6565
if(report.uvthreadResourceUsage)
6666
sections.push('uvthreadResourceUsage');
6767

68+
if(isJavaScriptThreadReport)
69+
sections.push('javascriptStack','javascriptHeap');
70+
6871
checkForUnknownFields(report,sections);
6972
sections.forEach((section)=>{
7073
assert(report.hasOwnProperty(section));
@@ -163,19 +166,6 @@ function _validateContent(report, fields = []){
163166
});
164167
assert.strictEqual(header.host,os.hostname());
165168

166-
// Verify the format of the javascriptStack section.
167-
checkForUnknownFields(report.javascriptStack,
168-
['message','stack','errorProperties']);
169-
assert.strictEqual(typeofreport.javascriptStack.errorProperties,
170-
'object');
171-
assert.strictEqual(typeofreport.javascriptStack.message,'string');
172-
if(report.javascriptStack.stack!==undefined){
173-
assert(Array.isArray(report.javascriptStack.stack));
174-
report.javascriptStack.stack.forEach((frame)=>{
175-
assert.strictEqual(typeofframe,'string');
176-
});
177-
}
178-
179169
// Verify the format of the nativeStack section.
180170
assert(Array.isArray(report.nativeStack));
181171
report.nativeStack.forEach((frame)=>{
@@ -186,26 +176,41 @@ function _validateContent(report, fields = []){
186176
assert.strictEqual(typeofframe.symbol,'string');
187177
});
188178

189-
// Verify the format of the javascriptHeap section.
190-
constheap=report.javascriptHeap;
191-
constjsHeapFields=['totalMemory','totalCommittedMemory','usedMemory',
192-
'availableMemory','memoryLimit','heapSpaces'];
193-
checkForUnknownFields(heap,jsHeapFields);
194-
assert(Number.isSafeInteger(heap.totalMemory));
195-
assert(Number.isSafeInteger(heap.totalCommittedMemory));
196-
assert(Number.isSafeInteger(heap.usedMemory));
197-
assert(Number.isSafeInteger(heap.availableMemory));
198-
assert(Number.isSafeInteger(heap.memoryLimit));
199-
assert(typeofheap.heapSpaces==='object'&&heap.heapSpaces!==null);
200-
constheapSpaceFields=['memorySize','committedMemory','capacity','used',
201-
'available'];
202-
Object.keys(heap.heapSpaces).forEach((spaceName)=>{
203-
constspace=heap.heapSpaces[spaceName];
204-
checkForUnknownFields(space,heapSpaceFields);
205-
heapSpaceFields.forEach((field)=>{
206-
assert(Number.isSafeInteger(space[field]));
179+
if(isJavaScriptThreadReport){
180+
// Verify the format of the javascriptStack section.
181+
checkForUnknownFields(report.javascriptStack,
182+
['message','stack','errorProperties']);
183+
assert.strictEqual(typeofreport.javascriptStack.errorProperties,
184+
'object');
185+
assert.strictEqual(typeofreport.javascriptStack.message,'string');
186+
if(report.javascriptStack.stack!==undefined){
187+
assert(Array.isArray(report.javascriptStack.stack));
188+
report.javascriptStack.stack.forEach((frame)=>{
189+
assert.strictEqual(typeofframe,'string');
190+
});
191+
}
192+
193+
// Verify the format of the javascriptHeap section.
194+
constheap=report.javascriptHeap;
195+
constjsHeapFields=['totalMemory','totalCommittedMemory','usedMemory',
196+
'availableMemory','memoryLimit','heapSpaces'];
197+
checkForUnknownFields(heap,jsHeapFields);
198+
assert(Number.isSafeInteger(heap.totalMemory));
199+
assert(Number.isSafeInteger(heap.totalCommittedMemory));
200+
assert(Number.isSafeInteger(heap.usedMemory));
201+
assert(Number.isSafeInteger(heap.availableMemory));
202+
assert(Number.isSafeInteger(heap.memoryLimit));
203+
assert(typeofheap.heapSpaces==='object'&&heap.heapSpaces!==null);
204+
constheapSpaceFields=['memorySize','committedMemory','capacity',
205+
'used','available'];
206+
Object.keys(heap.heapSpaces).forEach((spaceName)=>{
207+
constspace=heap.heapSpaces[spaceName];
208+
checkForUnknownFields(space,heapSpaceFields);
209+
heapSpaceFields.forEach((field)=>{
210+
assert(Number.isSafeInteger(space[field]));
211+
});
207212
});
208-
});
213+
}
209214

210215
// Verify the format of the resourceUsage section.
211216
constusage=report.resourceUsage;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
constcommon=require('../../common');
3+
consthelper=require('../../common/report.js');
4+
consttmpdir=require('../../common/tmpdir');
5+
6+
constassert=require('assert');
7+
constchild_process=require('child_process');
8+
consttest_fatal=require(`./build/${common.buildType}/test_fatal`);
9+
10+
if(common.buildType==='Debug')
11+
common.skip('as this will currently fail with a Debug check '+
12+
'in v8::Isolate::GetCurrent()');
13+
14+
// Test in a child process because the test code will trigger a fatal error
15+
// that crashes the process.
16+
if(process.argv[2]==='child'){
17+
test_fatal.TestThread();
18+
// Busy loop to allow the work thread to abort.
19+
while(true){}
20+
}
21+
22+
tmpdir.refresh();
23+
constp=child_process.spawnSync(
24+
process.execPath,
25+
['--report-on-fatalerror',__filename,'child'],
26+
{cwd: tmpdir.path});
27+
assert.ifError(p.error);
28+
assert.ok(p.stderr.toString().includes(
29+
'FATAL ERROR: work_thread foobar'));
30+
assert.ok(p.status===134||p.signal==='SIGABRT');
31+
32+
constreports=helper.findReports(p.pid,tmpdir.path);
33+
assert.strictEqual(reports.length,1);
34+
35+
constreport=reports[0];
36+
helper.validate(report);

0 commit comments

Comments
(0)