karma-runner / karma-runner/karma
Server(config, callback).start() causes node process to hang
- Dominant language
- JavaScript
- Stars
- 12k
- Forks
- 1.7k
- PR merge metrics
- No merged PRs in 30d
Description
### Expected behaviour
When a karma server has finished running, it should clean up so that node can exit, e.g.:
```JavaScript
new Server(config, callback).start()
```
### Actual behaviour
The node process hangs, and doesn't exit for upwards of a few minutes.
### Environment Details
- Latest Karma version (1.7.1/master branch):
- Uses the repo karma.conf.js file: [test/client/karma.conf.js](karma/test/client/karma.conf.js) with ChromeHeadless as the browser
### Steps to reproduce the behaviour
Note: This isn't 100% repo (as sometimes `writeBuffer` is empty when karma server calls `.disconnect` on the socket, see below for more details).
1. Create a karma test runner file, e.g.:
```JavaScript
var Server = require('./lib/server')
new Server({
configFile: "...karma-master/test/client/karma.conf.js",
reporters: ['dots'],
singleRun: true
}, (exitCode) => {
console.log(`Exited with code: ${exitCode}`)
}).start()
```
2. run from commandline: `node runkarma.js`
3. re-run if repo doesn't hit
### Cause
From debugging under node --inspect I see an engine.io socket stays alive preventing node from exiting.
Furthermore I see its caused by the `writeBuffer` containing messages preventing `closeTransport` from being called.
file: [engine.io\lib\socket.js](https://github.com/socketio/engine.io/blob/2abb217e26fb58e49c2590d74b2aae36dbe365cc/lib/socket.js#L463-L474)
```JavaScript
Socket.prototype.close = function (discard) {
if ('open' !== this.readyState) return;
this.readyState = 'closing';
if (this.writeBuffer.length) {
this.once('drain', this.closeTransport.bind(this, discard));
return;
}
this.closeTransport(discard);
};
```
Even more specifically its because the socket needs to cleanup the pingTimeout, which is done inside [onClose](https://github.com/socketio/engine.io/blob/2abb217e26fb58e49c2590d74b2aae36dbe365cc/lib/socket.js#L305) which is called by [closeTransport](https://github.com/socketio/engine.io/blob/2abb217e26fb58e49c2590d74b2aae36dbe365cc/lib/socket.js#L485).
### Note
Although the default behavior is to have the callback call process.exit, it doesn't work in our environment because:
1. We use karma inside a gulp task, which then runs subsequent tasks, so we don't want to exit straight away
2. We use "gulp watch" to run build/test tasks and this causes the subsequent watch tasks to stall
3. I see in the main repo they use grunt to spawn a child process, however we use JavaScript to configure the karma config, so that won't be a clean solution, and
Contributor guide
Assessment
This issue has not been assessed yet.