node-oom-heapdump 2.1.0-progress.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +2 -2
- package/.github/workflows/publish-native-assets-to-github-releases.yml +37 -37
- package/.travis.yml +13 -9
- package/CHANGELOG.md +103 -84
- package/LICENSE +21 -21
- package/README.md +143 -143
- package/binding.gyp +9 -9
- package/build/binding.sln +19 -0
- package/build/node_oom_heapdump_native.vcxproj +145 -0
- package/build/node_oom_heapdump_native.vcxproj.filters +14 -0
- package/index.js +122 -133
- package/lib/cpuProfileWorker.js +48 -48
- package/lib/heapdumpWorker.js +48 -48
- package/lib/index.js +193 -227
- package/lib/node_oom_heapdump_native.cc +119 -110
- package/package.json +50 -51
- package/tests/index.js +27 -27
- package/tests/long_running_process.js +26 -26
- package/tests/long_running_process_cpu.js +34 -34
- package/tests/oom_app.js +21 -21
- package/build/Makefile +0 -324
- package/build/binding.Makefile +0 -6
- package/build/node_oom_heapdump_native.target.mk +0 -157
package/lib/index.js
CHANGED
@@ -1,228 +1,194 @@
|
|
1
|
-
let cp = require("child_process");
|
2
|
-
let fs = require("fs");
|
3
|
-
let path = require("path");
|
4
|
-
|
5
|
-
class NodeOomHeapDumpImpl {
|
6
|
-
constructor(options) {
|
7
|
-
this._opts = options;
|
8
|
-
this._files = [];
|
9
|
-
this._busy = false;
|
10
|
-
this._count = 0;
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
this.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
});
|
118
|
-
}
|
119
|
-
|
120
|
-
/**
|
121
|
-
*
|
122
|
-
* @param {String}
|
123
|
-
* @
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
} else {
|
195
|
-
resolve(path);
|
196
|
-
}
|
197
|
-
});
|
198
|
-
} else {
|
199
|
-
reject(new Error("File not found:" + path));
|
200
|
-
}
|
201
|
-
});
|
202
|
-
}
|
203
|
-
|
204
|
-
/**
|
205
|
-
* Returns a proper snapshot path, based on the given parameter
|
206
|
-
* @param {String} snapshotPath
|
207
|
-
* @param {String} logPrefix
|
208
|
-
* @return {String} path
|
209
|
-
*/
|
210
|
-
_getHeapSnapshotPath(snapshotPath, logPrefix) {
|
211
|
-
if (!snapshotPath) {
|
212
|
-
snapshotPath = path.resolve(__dirname, "../heapsnapshot-" + Date.now());
|
213
|
-
}
|
214
|
-
if (logPrefix === "OoM" && this._opts.addTimestamp) {
|
215
|
-
if (snapshotPath.endsWith(".heapsnapshot")) {
|
216
|
-
snapshotPath = snapshotPath.replace(".heapsnapshot", "");
|
217
|
-
}
|
218
|
-
// in case of OoM error, add timestamp if needed
|
219
|
-
snapshotPath += "-" + Date.now();
|
220
|
-
}
|
221
|
-
if (!snapshotPath.endsWith(".heapsnapshot")) {
|
222
|
-
snapshotPath += ".heapsnapshot";
|
223
|
-
}
|
224
|
-
return snapshotPath;
|
225
|
-
}
|
226
|
-
}
|
227
|
-
|
1
|
+
let cp = require("child_process");
|
2
|
+
let fs = require("fs");
|
3
|
+
let path = require("path");
|
4
|
+
|
5
|
+
class NodeOomHeapDumpImpl {
|
6
|
+
constructor(options) {
|
7
|
+
this._opts = options;
|
8
|
+
this._files = [];
|
9
|
+
this._busy = false;
|
10
|
+
this._count = 0;
|
11
|
+
|
12
|
+
if (this._opts.heapdumpOnOOM) {
|
13
|
+
if (options.OOMImplementation === "NATIVE_HOOK") {
|
14
|
+
require('bindings')('node_oom_heapdump_native.node').call(this._getHeapSnapshotPath(this._opts.path), this._opts.addTimestamp);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Calls the designated worker and returns a promise
|
22
|
+
* @param {String} workerPath - path of the worker
|
23
|
+
* @param {String[]} workerArgs - arguments to worker
|
24
|
+
* @return {Promise} resolve on success, reject on error
|
25
|
+
*/
|
26
|
+
_callWorker(workerPath, workerArgs) {
|
27
|
+
if (this._busy) {
|
28
|
+
return new Promise((resolve, reject) => {
|
29
|
+
reject(new Error("A CPU profile or heapdump is already being created, please retry later."));
|
30
|
+
});
|
31
|
+
}
|
32
|
+
|
33
|
+
var args = [path.resolve(__dirname, workerPath)].concat(workerArgs);
|
34
|
+
|
35
|
+
// use 'require-main-filename' module instead of require.main.filename, see https://github.com/blueconic/node-oom-heapdump/issues/3
|
36
|
+
let mainFilename = require('require-main-filename')();
|
37
|
+
|
38
|
+
// start worker
|
39
|
+
let child = cp.spawn('node', args, {
|
40
|
+
cmd: path.dirname(mainFilename),
|
41
|
+
stdio: 'inherit'
|
42
|
+
});
|
43
|
+
|
44
|
+
return new Promise((resolve, reject) => {
|
45
|
+
this._busy = true;
|
46
|
+
var error = null;
|
47
|
+
|
48
|
+
child.on('error', (err) => {
|
49
|
+
error = err;
|
50
|
+
reject(err);
|
51
|
+
});
|
52
|
+
child.on('exit', (code) => {
|
53
|
+
if (!error) {
|
54
|
+
if (code === 0) {
|
55
|
+
resolve();
|
56
|
+
} else {
|
57
|
+
reject(new Error("Worker exited with statusCode: " + code));
|
58
|
+
}
|
59
|
+
}
|
60
|
+
this._busy = false;
|
61
|
+
});
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Returns the path to the created heap snapshot in a promise, or rejects on error
|
67
|
+
* @param {String} snapshotPath - path of the snapshot
|
68
|
+
* @param {String} logPrefix - optional log prefix message when heapdump is created
|
69
|
+
* @return {Promise} the heap snapshot path on success or error on rejection
|
70
|
+
*/
|
71
|
+
createHeapSnapshot(snapshotPath, logPrefix) {
|
72
|
+
snapshotPath = this._getHeapSnapshotPath(snapshotPath, logPrefix);
|
73
|
+
|
74
|
+
// start OoMworker to create heapdump
|
75
|
+
return this._callWorker('./heapdumpWorker.js', [this._opts.port, snapshotPath, logPrefix || ""]).then(() => {
|
76
|
+
if (logPrefix === "OoM") {
|
77
|
+
this._count++;
|
78
|
+
}
|
79
|
+
if (!this._files.includes(snapshotPath)) {
|
80
|
+
this._files.push(snapshotPath);
|
81
|
+
}
|
82
|
+
return snapshotPath;
|
83
|
+
});
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Returns the path to the created CPU profile in a promise, or rejects on error
|
88
|
+
* @param {String} cpuProfilePath - path of the CPU profile
|
89
|
+
* @param {number} duration - the duration of the cpu profile (in ms)
|
90
|
+
* @return {Promise} the CPU profile path on success or error on rejection
|
91
|
+
*/
|
92
|
+
createCpuProfile(cpuProfilePath, duration) {
|
93
|
+
if (!cpuProfilePath) {
|
94
|
+
cpuProfilePath = path.resolve(__dirname, "../cpuprofile-" + Date.now());
|
95
|
+
}
|
96
|
+
if (!cpuProfilePath.endsWith(".cpuprofile")) {
|
97
|
+
cpuProfilePath += ".cpuprofile";
|
98
|
+
}
|
99
|
+
|
100
|
+
// start OoMworker to create heapdump
|
101
|
+
return this._callWorker('./cpuProfileWorker.js', [this._opts.port, cpuProfilePath, duration]).then(() => {
|
102
|
+
if (!this._files.includes(cpuProfilePath)) {
|
103
|
+
this._files.push(cpuProfilePath);
|
104
|
+
}
|
105
|
+
return cpuProfilePath;
|
106
|
+
});
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Delete all created heap snapshots
|
111
|
+
*/
|
112
|
+
deleteAllHeapSnapshots() {
|
113
|
+
this._files.forEach((snapshotPath) => {
|
114
|
+
if (snapshotPath.endsWith(".heapsnapshot")) {
|
115
|
+
this.deleteHeapSnapshot(snapshotPath);
|
116
|
+
}
|
117
|
+
});
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Deletes a particular snapshot from disk
|
122
|
+
* @param {String} snapshotPath - path of the heap snapshot to delete
|
123
|
+
* @return {Promise}
|
124
|
+
*/
|
125
|
+
deleteHeapSnapshot(snapshotPath) {
|
126
|
+
return this._deleteFile(snapshotPath);
|
127
|
+
}
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Delete all created CPU profiles
|
131
|
+
*/
|
132
|
+
deleteAllCpuProfiles() {
|
133
|
+
this._files.forEach((path) => {
|
134
|
+
if (path.endsWith(".cpuprofile")) {
|
135
|
+
this.deleteCpuProfile(path);
|
136
|
+
}
|
137
|
+
});
|
138
|
+
}
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Deletes a particular CPU profile from disk
|
142
|
+
* @param {String} cpuProfilePath - path of the CPU profile to delete
|
143
|
+
* @return {Promise}
|
144
|
+
*/
|
145
|
+
deleteCpuProfile(cpuProfilePath) {
|
146
|
+
return this._deleteFile(cpuProfilePath);
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Deletes a given CPU profile or heapsnapshot from disk
|
151
|
+
* @param {String} path - path to the file to delete
|
152
|
+
* @return {Promise}
|
153
|
+
*/
|
154
|
+
_deleteFile(path) {
|
155
|
+
return new Promise((resolve, reject) => {
|
156
|
+
if (this._files.includes(path)) {
|
157
|
+
fs.unlink(path, (err) => {
|
158
|
+
if (err) {
|
159
|
+
reject(err);
|
160
|
+
} else {
|
161
|
+
resolve(path);
|
162
|
+
}
|
163
|
+
});
|
164
|
+
} else {
|
165
|
+
reject(new Error("File not found:" + path));
|
166
|
+
}
|
167
|
+
});
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Returns a proper snapshot path, based on the given parameter
|
172
|
+
* @param {String} snapshotPath
|
173
|
+
* @param {String} logPrefix
|
174
|
+
* @return {String} path
|
175
|
+
*/
|
176
|
+
_getHeapSnapshotPath(snapshotPath, logPrefix) {
|
177
|
+
if (!snapshotPath) {
|
178
|
+
snapshotPath = path.resolve(__dirname, "../heapsnapshot-" + Date.now());
|
179
|
+
}
|
180
|
+
if (logPrefix === "OoM" && this._opts.addTimestamp) {
|
181
|
+
if (snapshotPath.endsWith(".heapsnapshot")) {
|
182
|
+
snapshotPath = snapshotPath.replace(".heapsnapshot", "");
|
183
|
+
}
|
184
|
+
// in case of OoM error, add timestamp if needed
|
185
|
+
snapshotPath += "-" + Date.now();
|
186
|
+
}
|
187
|
+
if (!snapshotPath.endsWith(".heapsnapshot")) {
|
188
|
+
snapshotPath += ".heapsnapshot";
|
189
|
+
}
|
190
|
+
return snapshotPath;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
228
194
|
module.exports = NodeOomHeapDumpImpl;
|
@@ -1,110 +1,119 @@
|
|
1
|
-
#include <nan.h>
|
2
|
-
#include <v8-profiler.h>
|
3
|
-
#include <stdlib.h>
|
4
|
-
#if defined(_WIN32)
|
5
|
-
#include <time.h>
|
6
|
-
#define snprintf _snprintf
|
7
|
-
#else
|
8
|
-
#include <sys/time.h>
|
9
|
-
#endif
|
10
|
-
|
11
|
-
using namespace v8;
|
12
|
-
|
13
|
-
char filename[256];
|
14
|
-
bool addTimestamp;
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
virtual
|
24
|
-
|
25
|
-
size_t
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
}
|
45
|
-
|
46
|
-
|
47
|
-
if (addTimestamp) {
|
48
|
-
// Add timestamp to filename
|
49
|
-
time_t rawtime;
|
50
|
-
struct tm* timeinfo;
|
51
|
-
time(&rawtime);
|
52
|
-
timeinfo = localtime(&rawtime);
|
53
|
-
|
54
|
-
char * pch;
|
55
|
-
pch = strstr (filename,".heapsnapshot");
|
56
|
-
strncpy (pch,"",1);
|
57
|
-
strcat (filename, "-%Y%m%dT%H%M%S.heapsnapshot");
|
58
|
-
|
59
|
-
char newFilename[256];
|
60
|
-
strftime(newFilename, sizeof(filename), filename, timeinfo);
|
61
|
-
strcpy(filename, newFilename);
|
62
|
-
}
|
63
|
-
|
64
|
-
fprintf(stderr, "Generating Heapdump to '%s' now...\n", filename);
|
65
|
-
FILE* fp = fopen(filename, "w");
|
66
|
-
if (fp == NULL) abort();
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
#
|
100
|
-
|
101
|
-
#
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
1
|
+
#include <nan.h>
|
2
|
+
#include <v8-profiler.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#if defined(_WIN32)
|
5
|
+
#include <time.h>
|
6
|
+
#define snprintf _snprintf
|
7
|
+
#else
|
8
|
+
#include <sys/time.h>
|
9
|
+
#endif
|
10
|
+
|
11
|
+
using namespace v8;
|
12
|
+
|
13
|
+
char filename[256];
|
14
|
+
bool addTimestamp;
|
15
|
+
bool processingOOM = false;
|
16
|
+
|
17
|
+
class FileOutputStream: public OutputStream {
|
18
|
+
public:
|
19
|
+
FileOutputStream(FILE* stream): stream_(stream) { }
|
20
|
+
virtual int GetChunkSize() {
|
21
|
+
return 65536;
|
22
|
+
}
|
23
|
+
virtual void EndOfStream() { }
|
24
|
+
virtual WriteResult WriteAsciiChunk(char* data, int size) {
|
25
|
+
const size_t len = static_cast<size_t>(size);
|
26
|
+
size_t off = 0;
|
27
|
+
while (off < len && !feof(stream_) && !ferror(stream_))
|
28
|
+
off += fwrite(data + off, 1, len - off, stream_);
|
29
|
+
return off == len ? kContinue : kAbort;
|
30
|
+
}
|
31
|
+
|
32
|
+
private:
|
33
|
+
FILE* stream_;
|
34
|
+
};
|
35
|
+
|
36
|
+
size_t RaiseLimit(void* data, size_t current_heap_limit, size_t initial_heap_limit) {
|
37
|
+
return current_heap_limit + 10u * 1024 * 1024; // 10MiB
|
38
|
+
}
|
39
|
+
|
40
|
+
void OnOOMError(const char *location, bool is_heap_oom) {
|
41
|
+
if (processingOOM) {
|
42
|
+
fprintf(stderr, "FATAL: OnOOMError called more than once.\n");
|
43
|
+
exit(2);
|
44
|
+
}
|
45
|
+
processingOOM = true;
|
46
|
+
|
47
|
+
if (addTimestamp) {
|
48
|
+
// Add timestamp to filename
|
49
|
+
time_t rawtime;
|
50
|
+
struct tm* timeinfo;
|
51
|
+
time(&rawtime);
|
52
|
+
timeinfo = localtime(&rawtime);
|
53
|
+
|
54
|
+
char * pch;
|
55
|
+
pch = strstr (filename,".heapsnapshot");
|
56
|
+
strncpy (pch,"",1);
|
57
|
+
strcat (filename, "-%Y%m%dT%H%M%S.heapsnapshot");
|
58
|
+
|
59
|
+
char newFilename[256];
|
60
|
+
strftime(newFilename, sizeof(filename), filename, timeinfo);
|
61
|
+
strcpy(filename, newFilename);
|
62
|
+
}
|
63
|
+
|
64
|
+
fprintf(stderr, "Generating Heapdump to '%s' now...\n", filename);
|
65
|
+
FILE* fp = fopen(filename, "w");
|
66
|
+
if (fp == NULL) abort();
|
67
|
+
|
68
|
+
auto* isolate = v8::Isolate::GetCurrent();
|
69
|
+
|
70
|
+
// Capturing a heap snapshot forces a garbage collection which can, in turn,
|
71
|
+
// trigger the OOM flow which causes recursion. To prevent this, this callback
|
72
|
+
// will raise the heap limit if the GC tries to go down that path again.
|
73
|
+
// Normally we would want to add a call to RemoveNearHeapLimitCallback() after
|
74
|
+
// we are done, but that is not necessary since we exit() before it matters.
|
75
|
+
isolate->AddNearHeapLimitCallback(RaiseLimit, nullptr);
|
76
|
+
|
77
|
+
// Create heapdump, depending on which Node.js version this can differ
|
78
|
+
// for now, just support Node.js 7 and higher
|
79
|
+
const HeapSnapshot* snap = isolate->GetHeapProfiler()->TakeHeapSnapshot();
|
80
|
+
|
81
|
+
FileOutputStream stream(fp);
|
82
|
+
snap->Serialize(&stream, HeapSnapshot::kJSON);
|
83
|
+
fclose(fp);
|
84
|
+
|
85
|
+
fprintf(stderr, "Done! Exiting process now.\n");
|
86
|
+
exit(1);
|
87
|
+
}
|
88
|
+
|
89
|
+
void ParseArgumentsAndSetErrorHandler(const FunctionCallbackInfo<Value>& args) {
|
90
|
+
Isolate* isolate = args.GetIsolate();
|
91
|
+
isolate->SetOOMErrorHandler(OnOOMError);
|
92
|
+
|
93
|
+
// parse JS arguments
|
94
|
+
// 1: filename
|
95
|
+
// 2: addTimestamp boolean
|
96
|
+
#if NODE_VERSION_AT_LEAST(13, 0, 0)
|
97
|
+
Local<Context> context = isolate->GetCurrentContext();
|
98
|
+
String::Utf8Value fArg(isolate, args[0]->ToString(context).ToLocalChecked());
|
99
|
+
#elif NODE_VERSION_AT_LEAST(12, 0, 0)
|
100
|
+
String::Utf8Value fArg(isolate, args[0]->ToString(isolate));
|
101
|
+
#elif NODE_VERSION_AT_LEAST(9, 0, 0)
|
102
|
+
String::Utf8Value fArg(isolate, args[0]->ToString());
|
103
|
+
#else
|
104
|
+
String::Utf8Value fArg(args[0]->ToString());
|
105
|
+
#endif
|
106
|
+
strncpy(filename, (const char*)(*fArg), sizeof(filename) - 1);
|
107
|
+
|
108
|
+
#if NODE_VERSION_AT_LEAST(12, 0, 0)
|
109
|
+
addTimestamp = args[1]->BooleanValue(isolate);
|
110
|
+
#else
|
111
|
+
addTimestamp = args[1]->BooleanValue();
|
112
|
+
#endif
|
113
|
+
}
|
114
|
+
|
115
|
+
void init(Local<Object> exports) {
|
116
|
+
NODE_SET_METHOD(exports, "call", ParseArgumentsAndSetErrorHandler);
|
117
|
+
}
|
118
|
+
|
119
|
+
NODE_MODULE(NODE_OOM_HEAPDUMP_NATIVE, init)
|