Bug 1631451 - [devtools] Bail out if DevToolsClient.close becomes reentrant. r=nchevobbe

Close method may be called by the transport on close.
This was highlighted by browser_target_from_url.js
Surprisingly devtools/shared/tests/xpcshell/test_debugger_client.js
tries quite hard to cover such issue, but we seem to get yet another type of reentrancy.
This probably depends on WebSocketTransport, which is a bit hard to get covered.
No test seems to be spawning a WebSocket DevToolsServer...

Differential Revision: https://phabricator.services.mozilla.com/D107988
This commit is contained in:
Alexandre Poirot 2021-03-17 23:46:36 +00:00
Родитель cc89c462df
Коммит 1c1911097e
2 изменённых файлов: 20 добавлений и 24 удалений

Просмотреть файл

@ -113,33 +113,26 @@ DevToolsClient.prototype = {
* Resolves after the underlying transport is closed.
*/
close() {
const promise = new Promise(resolve => {
// Disable detach event notifications, because event handlers will be in a
// cleared scope by the time they run.
this._eventsEnabled = false;
if (this._closed) {
return Promise.resolve();
}
if (this._closePromise) {
return this._closePromise;
}
// Immediately set the destroy promise,
// as the following code is fully synchronous and can be reentrant.
this._closePromise = this.once("closed");
const cleanup = () => {
if (this._transport) {
this._transport.close();
}
this._transport = null;
};
// Disable detach event notifications, because event handlers will be in a
// cleared scope by the time they run.
this._eventsEnabled = false;
// If the connection is already closed,
// there is no need to detach client
// as we won't be able to send any message.
if (this._closed) {
cleanup();
resolve();
return;
}
if (this._transport) {
this._transport.close();
this._transport = null;
}
this.once("closed", resolve);
cleanup();
});
return promise;
return this._closePromise;
},
/**

Просмотреть файл

@ -38,6 +38,9 @@ WebSocketDebuggerTransport.prototype = {
},
close() {
if (!this.socket) {
return;
}
this.emit("close");
this.active = false;