Skip to content

Commit 62bce52

Browse files
committed
first commit
0 parents  commit 62bce52

File tree

7 files changed

+318
-0
lines changed

7 files changed

+318
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Mathias Buus
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# why-is-node-running
2+
3+
Node is running but you don't know why? why-is-node-running is here to help you.
4+
5+
```
6+
npm install why-is-node-running
7+
```
8+
9+
## Usage
10+
11+
``` js
12+
var log = require('why-is-node-running')
13+
var net = require('net')
14+
15+
function createServer () {
16+
var server = net.createServer()
17+
setInterval(function () {}, 1000)
18+
server.listen(0)
19+
}
20+
21+
createServer()
22+
createServer()
23+
24+
setTimeout(function () {
25+
log() // logs out active handles that are keeping node running
26+
}, 100)
27+
```
28+
29+
Running the above will print
30+
31+
```
32+
There are 4 known handle(s) keeping the process running and 0 unknown
33+
Known handles:
34+
35+
/Users/maf/dev/node_modules/why-is-node-running/example.js:6 - setInterval(function () {}, 1000)
36+
/Users/maf/dev/node_modules/why-is-node-running/example.js:10 - createServer()
37+
38+
/Users/maf/dev/node_modules/why-is-node-running/example.js:7 - server.listen(0)
39+
/Users/maf/dev/node_modules/why-is-node-running/example.js:10 - createServer()
40+
41+
/Users/maf/dev/node_modules/why-is-node-running/example.js:7 - server.listen(0)
42+
/Users/maf/dev/node_modules/why-is-node-running/example.js:11 - createServer()
43+
44+
/Users/maf/dev/node_modules/why-is-node-running/example.js:13 - setTimeout(function () {
45+
```
46+
47+
## License
48+
49+
MIT

core.js

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// lifted from node core, https://github.com/nodejs/node/blob/88307974e60346bc98c4e9f70a2b6918ccb6844f/src/node.js
2+
// needed to instrument timers
3+
4+
exports.NativeModule = NativeModule
5+
exports.globalTimeouts = globalTimeouts
6+
7+
var ContextifyScript = process.binding('contextify').ContextifyScript;
8+
function runInThisContext(code, options) {
9+
var script = new ContextifyScript(code, options);
10+
return script.runInThisContext();
11+
}
12+
13+
function globalTimeouts () {
14+
const timers = NativeModule.require('timers');
15+
global.clearImmediate = timers.clearImmediate;
16+
global.clearInterval = timers.clearInterval;
17+
global.clearTimeout = timers.clearTimeout;
18+
global.setImmediate = timers.setImmediate;
19+
global.setInterval = timers.setInterval;
20+
global.setTimeout = timers.setTimeout;
21+
};
22+
23+
function NativeModule(id) {
24+
this.filename = id + '.js';
25+
this.id = id;
26+
this.exports = {};
27+
this.loaded = false;
28+
}
29+
30+
NativeModule._source = process.binding('natives');
31+
NativeModule._cache = {};
32+
33+
NativeModule.require = function(id) {
34+
if (id == 'native_module') {
35+
return NativeModule;
36+
}
37+
38+
var cached = NativeModule.getCached(id);
39+
if (cached) {
40+
return cached.exports;
41+
}
42+
43+
if (!NativeModule.exists(id)) {
44+
throw new Error('No such native module ' + id);
45+
}
46+
47+
process.moduleLoadList.push('NativeModule ' + id);
48+
49+
var nativeModule = new NativeModule(id);
50+
51+
nativeModule.cache();
52+
nativeModule.compile();
53+
54+
return nativeModule.exports;
55+
};
56+
57+
NativeModule.getCached = function(id) {
58+
return NativeModule._cache[id];
59+
};
60+
61+
NativeModule.exists = function(id) {
62+
return NativeModule._source.hasOwnProperty(id);
63+
};
64+
65+
const EXPOSE_INTERNALS = process.execArgv.some(function(arg) {
66+
return arg.match(/^--expose[-_]internals$/);
67+
});
68+
69+
if (EXPOSE_INTERNALS) {
70+
NativeModule.nonInternalExists = NativeModule.exists;
71+
72+
NativeModule.isInternal = function(id) {
73+
return false;
74+
};
75+
} else {
76+
NativeModule.nonInternalExists = function(id) {
77+
return NativeModule.exists(id) && !NativeModule.isInternal(id);
78+
};
79+
80+
NativeModule.isInternal = function(id) {
81+
return id.startsWith('internal/');
82+
};
83+
}
84+
85+
86+
NativeModule.getSource = function(id) {
87+
return NativeModule._source[id];
88+
};
89+
90+
NativeModule.wrap = function(script) {
91+
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
92+
};
93+
94+
NativeModule.wrapper = [
95+
'(function (exports, require, module, __filename, __dirname) { ',
96+
'\n});'
97+
];
98+
99+
NativeModule.prototype.compile = function() {
100+
var source = NativeModule.getSource(this.id);
101+
source = NativeModule.wrap(source);
102+
103+
var fn = runInThisContext(source, {
104+
filename: this.filename,
105+
lineOffset: 0,
106+
displayErrors: true
107+
});
108+
fn(this.exports, NativeModule.require, this, this.filename);
109+
110+
this.loaded = true;
111+
};
112+
113+
NativeModule.prototype.cache = function() {
114+
NativeModule._cache[this.id] = this;
115+
};

example.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var log = require('why-is-node-running')
2+
var net = require('net')
3+
4+
function createServer () {
5+
var server = net.createServer()
6+
setInterval(function () {}, 1000)
7+
server.listen(0)
8+
}
9+
10+
createServer()
11+
createServer()
12+
13+
setTimeout(function () {
14+
log()
15+
}, 100)

index.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
var core = require('./core')
2+
3+
var b = process.binding
4+
5+
process.binding = function (name) {
6+
var loaded = b(name)
7+
var cpy = {}
8+
9+
Object.keys(loaded).forEach(function (prop) {
10+
if (typeof loaded[prop] === 'function' && loaded[prop].prototype) {
11+
var wrap = function () {
12+
var handle = new loaded[prop]()
13+
var e = new Error('whatevs')
14+
var stacks = require('stackback')(e)
15+
var path = require('path')
16+
17+
handle.__WHY_IS_NODE_RUNNING__ = []
18+
19+
for (var i = 1; i < stacks.length; i++) {
20+
handle.__WHY_IS_NODE_RUNNING__.push(stacks[i])
21+
}
22+
23+
return handle
24+
}
25+
26+
Object.keys(loaded[prop]).forEach(function (name) {
27+
wrap[name] = loaded[prop][name]
28+
})
29+
30+
if (/^[A-Z]/.test(prop)) {
31+
cpy[prop] = wrap
32+
} else {
33+
cpy[prop] = loaded[prop]
34+
}
35+
} else {
36+
cpy[prop] = loaded[prop]
37+
}
38+
})
39+
40+
return cpy
41+
}
42+
43+
core.globalTimeouts()
44+
45+
module.exports = function () {
46+
var handles = process._getActiveHandles()
47+
var unknown = 0
48+
var known = []
49+
50+
handles.forEach(function (handle) {
51+
var stacks = findStacks(handle, 0)
52+
if (stacks) {
53+
known.push(stacks)
54+
return
55+
}
56+
57+
unknown++
58+
})
59+
60+
console.error('There are %d known handle(s) keeping the process running and %d unknown', known.length, unknown)
61+
console.error('Known handles:\n')
62+
known.forEach(function (stacks, i) {
63+
stacks = stacks.filter(function (s) {
64+
return s.getFileName().indexOf(require('path').sep) > -1
65+
})
66+
67+
if (!stacks[0]) {
68+
console.error('(unknown stack trace)')
69+
} else {
70+
var padding = ''
71+
stacks.forEach(function (s) {
72+
var pad = (s.getFileName() + ':' + s.getLineNumber()).replace(/./g, ' ')
73+
if (pad.length > padding.length) padding = pad
74+
})
75+
stacks.forEach(function (s) {
76+
var src = require('fs').readFileSync(s.getFileName(), 'utf-8').split(/\n|\r\n/)
77+
var prefix = s.getFileName() + ':' + s.getLineNumber()
78+
console.error(prefix + padding.slice(prefix.length) + ' - ' + src[s.getLineNumber() - 1].trim())
79+
})
80+
}
81+
console.error()
82+
})
83+
}
84+
85+
function findStacks (obj, depth) {
86+
if (depth === 10) return null
87+
88+
var keys = Object.keys(obj)
89+
for (var i = 0; i < keys.length; i++) {
90+
var val = obj[keys[i]]
91+
if (keys[i] === '__WHY_IS_NODE_RUNNING__') return val
92+
if (typeof val === 'object' && val) {
93+
val = findStacks(val, depth + 1)
94+
if (val) return val
95+
}
96+
}
97+
}

package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "why-is-node-running",
3+
"version": "0.0.0",
4+
"description": "Node is running but you don't know why? why-is-node-running is here to help you.",
5+
"main": "index.js",
6+
"dependencies": {
7+
"stackback": "0.0.2"
8+
},
9+
"devDependencies": {},
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/mafintosh/why-is-node-running.git"
13+
},
14+
"author": "Mathias Buus (@mafintosh)",
15+
"license": "MIT",
16+
"bugs": {
17+
"url": "https://github.com/mafintosh/why-is-node-running/issues"
18+
},
19+
"homepage": "https://github.com/mafintosh/why-is-node-running"
20+
}

0 commit comments

Comments
 (0)