Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: _disconnect causes uncaught exception and process to crash if using ws library #197

Open
titanism opened this issue Jun 26, 2024 · 10 comments

Comments

@titanism
Copy link

There is a bug in the codebase right now in that _disconnect is invoked which subsequently calls this._ws.close. Despite there being a try/catch wrapper, if you use the ws library, an exception is thrown and your process will exit.

ReconnectingWebSocket.prototype._disconnect = function (code, reason) {
  if (code === undefined) {
    code = 1000;
  }

  this._clearTimeouts();
  if (!this._ws) {
    return;
  }

  this._removeListeners();
  try {
+    if (this._ws.readyState === ReconnectingWebSocket.OPEN) {
+      this._ws.close(code, reason);
+    }
-    this._ws.close(code, reason);
    this._handleClose(new CloseEvent(code, reason, this));
  } catch (err) {
    console.log('das error', err);
  }
};

cc @bytemain @abdelmagied94 @Zerounary can you please merge this fix into your library at https://github.com/opensumi/reconnecting-websocket for the npm package @opensumi/reconnecting-websocket and patch version bump and publish to npm afterwards to v4.4.1 (it currently on v4.4.0)

@titanism
Copy link
Author

You can see the code here from ws that causes this uncaught exception:

  close(code, data) {
    if (this.readyState === WebSocket.CLOSED) return;
    if (this.readyState === WebSocket.CONNECTING) {
      const msg = 'WebSocket was closed before the connection was established';
      abortHandshake(this, this._req, msg); // <----------- RIGHT HERE EXCEPTION IS THROWN
      return;
    }

https://github.com/websockets/ws/blob/0d1b5e6c4acad16a6b1a1904426eb266a5ba2f72/lib/websocket.js#L290-L294

abortHandshake will throw the error on the process.nextTick here https://github.com/websockets/ws/blob/0d1b5e6c4acad16a6b1a1904426eb266a5ba2f72/lib/websocket.js#L1096

@bytemain
Copy link

How do you call _disconnect? this error seems to happen when you manually invoke reconnect method? could you check the readyState before invoke?

@titanism
Copy link
Author

@bytemain This gets invoked when you call wsp.close() or when a timeout occurs, e.g. _handleError is called which calls this._disconnect, which then triggers this.

@bytemain
Copy link

bytemain commented Jun 27, 2024

I see it, seems a bug here, might we should check this._ws.readyState === this.CLOSING first?

CleanShot 2024-06-27 at 13 17 09@2x

@titanism
Copy link
Author

Actually what is probably better is to check if readyState !== CONNECTING

@bytemain
Copy link

but when ws abort connection, it set readyState to CLOSING first: https://github.com/websockets/ws/blob/0d1b5e6c4acad16a6b1a1904426eb266a5ba2f72/lib/websocket.js#L1077

@titanism
Copy link
Author

The logic that throws this error results from checking if it is equal to CONNECTING as mentioned already.

Please see the code here https://github.com/websockets/ws/blob/0d1b5e6c4acad16a6b1a1904426eb266a5ba2f72/lib/websocket.js#L290-L294.

Therefore, it is is NOT connecting, !== CONNECTING then don't call close.

@bytemain

@bytemain
Copy link

why? we actually need abort connection that is connecting, because here we are reconnecting, if dont abort it, we will have orphen conection

@titanism
Copy link
Author

It seems to throw an uncaught exception if you try to call close in an instance of ws that is in a CONNECTING state (even if you wrap it with a try/catch block).

titanism added a commit to forwardemail/forwardemail.net that referenced this issue Jun 27, 2024
…reconnecting-websocket (as previous package no longer maintained), increased SQLite busy_timeout from 15s to 30s, added courtesy email to customers if they are attempting to use IMAP/POP3 but do not have IMAP enabled on the alias yet (once a week), added _disconnect fix per <pladaria/reconnecting-websocket#197> (otherwise exception is thrown and process restarts), fixed spam/junk/trash check, added analysis_limit=400 to speed up pragma optimize, fixed POP3 exception with writeStream, fixed SEARCH bug of SqliteError - too many SQL variables due to SQLITE_MAX_VARIABLE_NUMBER max of 999, fixed RangeError: Maximum call stack size exceeded with msgpackr and Error objects, fixed payload.id missing for backups, only check for backups during read operation such as GETQUOTAROOT on SQLite server only, sync tmp with db every time user attempts to fetch mail (once every 10s)
@titanism
Copy link
Author

@bytemain just making sure you saw my comment here opensumi#10 (comment)

Thank you! 🙏 🙇 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants