websockets / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
21.59k stars 2.42k forks source link

ERROR uncaughtException: Cannot read property 'aborted' of null #1229

Closed d4rkstar closed 6 years ago

d4rkstar commented 6 years ago

https://github.com/websockets/ws/blob/d0741faeec6fc6bc6db163545b3534ed822f6cf3/lib/WebSocket.js#L639

It seems that, if a previous error occurs, this._req is null. So this line seems to produce an exception.

lpinca commented 6 years ago

See #1201, is there a way to reproduce the issue?

lpinca commented 6 years ago

Are you by any chance throwing an error from the 'error' listener and using process.once('uncaughtException')?

This is the only way I can make http.ClientRequest emit the 'error' event twice on Node.js 8:

const http = require('http');

const host = 'a'.repeat(10);
let req = http.get({ host });

req.on('error', (err) => {
  if (req.aborted) return;
  req = null;
  throw err;
});

process.once('uncaughtException', () => {});

Can you also please add more details?

Thanks.

d4rkstar commented 6 years ago

Hello Luigi, thank you for your feedback. Fortunately i've logs about the error :)

Before, i'll give you more informations about my environment:

Using webstomp over websocket with SSL:

let stomp_url = 'wss://remotehost:8443/ws';
self.client = webstomp.over(new WebSocket(stomp_url), options);

The trace:

2017-10-24T09:33:14.779Z ERROR uncaughtException: connect ECONNREFUSED xxx.xxx.xxx.xxx:8443
        {"date":"Tue Oct 24 2017 11:33:14 GMT+0200 (CEST)","process":{"pid":23454,"uid":1001,"gid":1001,"cwd":"/home/myapp/myapp","execPath":"/usr/bin/node","version":"v8.6.0","argv":["/usr/bin/node","/home/myapp/myapp/www"],"memoryUsage":{"rss":91394048,"heapTotal":51220480,"heapUsed":38065344,"external":239175}},"os":{"loadavg":[0,0,0],"uptime":1794013},"trace":[{"column":11,"file":"util.js","function":"Object._errnoException","line":1019,"method":"_errnoException","native":false},{"column":20,"file":"util.js","function":"_exceptionWithHostPort","line":1041,"method":null,"native":false},{"column":14,"file":"net.js","function":"TCPConnectWrap.afterConnect [as oncomplete]","line":1175,"method":"afterConnect [as oncomplete]","native":false}],"stack":["Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:8443","    at Object._errnoException (util.js:1019:11)","    at _exceptionWithHostPort (util.js:1041:20)","    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1175:14)"]}

Regards

lpinca commented 6 years ago

Thanks, that seems a different error though (not the one in the issue title) and it isn't caught because you didn't add an 'error' listener to the WebSocket instance.

lpinca commented 6 years ago

Ok, I can reproduce with this code:

const WebSocket = require('ws');

const ws = new WebSocket('wss://localhost');

process.on('uncaughtException', (err) => {
  console.error(err);
});
$ node index.js
{ Error: connect ECONNREFUSED 127.0.0.1:443
    at Object._errnoException (util.js:1021:11)
    at _exceptionWithHostPort (util.js:1043:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1175:14)
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 443 }
TypeError: Cannot read property 'aborted' of null
    at ClientRequest._req.on (/home/luigi/1229/node_modules/ws/lib/WebSocket.js:646:19)
    at emitOne (events.js:115:13)
    at ClientRequest.emit (events.js:210:7)
    at TLSSocket.socketCloseListener (_http_client.js:361:9)
    at emitOne (events.js:120:20)
    at TLSSocket.emit (events.js:210:7)
    at _handle.close (net.js:547:12)
    at TCP.done [as _onclose] (_tls_wrap.js:356:7)

but this is not an issue in ws.

The problem here is the use of 'uncaughtException'. We are emitting an 'error' event here and if there are no listeners the error is thrown. The 'uncaughtException' listener prevents the process from exiting. The thrown error prevents this flag from being set and for this reason a second 'error' event is emitted.

This no longer happens in Node.js 9 (https://github.com/nodejs/node/commit/620ba41694) but there is nothing wrong also in previous versions of Node.js. 'uncaughtException' should not be used.

d4rkstar commented 6 years ago

Thank you again Luigi. Will change my code and will update or close this issue

lpinca commented 6 years ago

Any update here?

lpinca commented 6 years ago

Closing due to inactivity. If your issue is still unresolved, please comment back and I will reopen this.

derwaldgeist commented 6 years ago

Having the same problem here when using ws in Electron.

damianobarbati commented 6 years ago

same here with electron!

ghost commented 5 years ago

Having the problem since I switched to the very first version in which you support handshakeTimeout (something around 3.0.2 or so)

From this version on up to the latest: If this sequence goes into "error", I'll receive an exception

TypeError: Cannot read property 'setHeader' of null

a couple of seconds after the error occurs. The first attempt fails as expected after 5s

Error: Opening handshake has timed out

If I repeat the sequence then, it immediately fails with

Error: connect EHOSTDOWN 192.168.188.98:8888 - Local (192.168.188.24:57769)

but then after 5 s the exception occurs. For me it looks like as if you would not terminate the handshakeTimer on error

        let server = new ws(argv.ws_uri, {handshakeTimeout: 5000})
            server.on('open', () => {
                server.send(JSON.stringify({
                    id: 1,
                    method: "ping",
                    params: {
                      interval: 3000
                    },
                    jsonrpc: "2.0"
                }))
            })
            server.on('message', (data) => {
                console.log(data)
                res.send("OK")
            })
            server.on('error', (error) => {
                console.log(error)

                res.send("ERROR "+error)
            })
lpinca commented 5 years ago

@accuware your issue is different from the one reported by the original poster. In your case it seems that

https://github.com/websockets/ws/blob/14d9088391ac4495d04e64d76c3b83d4e75f80e2/lib/websocket.js#L542

is called after the 'error' or the 'upgrade' event is emitted on the req object which would be a bug in Node.js. Are you able to create a reproducible test case?