fix QMP deadlock

This commit is contained in:
modeco80
2023-02-07 22:38:41 -05:00
parent 6419604aa6
commit 1637614c74

View File

@@ -38,25 +38,39 @@ export default class QMPClient extends EventEmitter {
} }
private async onData(data : Buffer) { private async onData(data : Buffer) {
var msgraw = data.toString(); let msgraw = data.toString();
var msg; let msg;
try {msg = JSON.parse(msgraw);}
catch {return;} try {
msg = JSON.parse(msgraw);
} catch {
return;
}
if (msg.QMP !== undefined) { if (msg.QMP !== undefined) {
if (this.sentConnected) {return;}; if (this.sentConnected)
return;
await this.execute({ execute: "qmp_capabilities" }); await this.execute({ execute: "qmp_capabilities" });
this.emit('connected'); this.emit('connected');
this.sentConnected = true; 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() { private onClose() {
this.connected = false; this.connected = false;
this.sentConnected = false; this.sentConnected = false;
if (this.socket.readyState === 'open') if (this.socket.readyState === 'open')
this.socket.destroy(); this.socket.destroy();
this.cmdMutex.cancel(); this.cmdMutex.cancel();
this.cmdMutex.release(); this.cmdMutex.release();
this.socket = new Socket(); this.socket = new Socket();
@@ -64,12 +78,16 @@ export default class QMPClient extends EventEmitter {
} }
async reboot() { async reboot() {
if (!this.connected) return; if (!this.connected)
return;
await this.execute({"execute": "system_reset"}); await this.execute({"execute": "system_reset"});
} }
async ExitQEMU() { async ExitQEMU() {
if (!this.connected) return; if (!this.connected)
return;
await this.execute({"execute": "quit"}); await this.execute({"execute": "quit"});
} }
@@ -86,15 +104,16 @@ export default class QMPClient extends EventEmitter {
this.socket.write(JSON.stringify(args)); this.socket.write(JSON.stringify(args));
}); });
}); });
} catch {res({})}; } catch {
res({});
}
res(result); res(result);
}); });
} }
runMonitorCmd(command : string) { runMonitorCmd(command : string) {
return new Promise(async (res, rej) => { return new Promise(async (res, rej) => {
var result : any = await this.execute({execute: "human-monitor-command", arguments: {"command-line": command}}); res(await this.execute({execute: "human-monitor-command", arguments: {"command-line": command}}));
res(result);
}); });
} }
} }