From 1637614c74d0f35f5bb09abca3b6eb2def9ef8fd Mon Sep 17 00:00:00 2001 From: modeco80 Date: Tue, 7 Feb 2023 22:38:41 -0500 Subject: [PATCH] fix QMP deadlock --- src/QMPClient.ts | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/QMPClient.ts b/src/QMPClient.ts index 0b9c183..cdd64c0 100644 --- a/src/QMPClient.ts +++ b/src/QMPClient.ts @@ -38,25 +38,39 @@ export default class QMPClient extends EventEmitter { } private async onData(data : Buffer) { - var msgraw = data.toString(); - var msg; - try {msg = JSON.parse(msgraw);} - catch {return;} + let msgraw = data.toString(); + let msg; + + try { + msg = JSON.parse(msgraw); + } catch { + return; + } + if (msg.QMP !== undefined) { - if (this.sentConnected) {return;}; + if (this.sentConnected) + return; + await this.execute({ execute: "qmp_capabilities" }); this.emit('connected'); this.sentConnected = true; } - if (msg.return !== undefined) this.emit("qmpreturn", msg.return); + if (msg.return !== undefined) + this.emit("qmpreturn", msg.return); + else + // for now just return an empty string. + // This is a giant hack but avoids a deadlock + this.emit("qmpreturn", ''); } private onClose() { this.connected = false; this.sentConnected = false; + if (this.socket.readyState === 'open') this.socket.destroy(); + this.cmdMutex.cancel(); this.cmdMutex.release(); this.socket = new Socket(); @@ -64,12 +78,16 @@ export default class QMPClient extends EventEmitter { } async reboot() { - if (!this.connected) return; + if (!this.connected) + return; + await this.execute({"execute": "system_reset"}); } async ExitQEMU() { - if (!this.connected) return; + if (!this.connected) + return; + await this.execute({"execute": "quit"}); } @@ -86,15 +104,16 @@ export default class QMPClient extends EventEmitter { this.socket.write(JSON.stringify(args)); }); }); - } catch {res({})}; + } catch { + res({}); + } res(result); }); } runMonitorCmd(command : string) { return new Promise(async (res, rej) => { - var result : any = await this.execute({execute: "human-monitor-command", arguments: {"command-line": command}}); - res(result); + res(await this.execute({execute: "human-monitor-command", arguments: {"command-line": command}})); }); } } \ No newline at end of file