qemu: Make sure stdin is open before writing

oops. Not sure how I didn't think of that.
This commit is contained in:
modeco80
2024-07-16 06:35:58 -04:00
parent 7413059193
commit 6a4c1e6ac2

View File

@@ -1,12 +1,11 @@
import { execa, execaCommand, ExecaChildProcess } from 'execa'; import { execaCommand, ExecaChildProcess } from 'execa';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { QmpClient, IQmpClientWriter, QmpEvent } from './QmpClient.js'; import { QmpClient, IQmpClientWriter, QmpEvent } from './QmpClient.js';
import { QemuDisplay } from './QemuDisplay.js'; import { QemuDisplay } from './QemuDisplay.js';
import { unlink } from 'node:fs/promises'; import { unlink } from 'node:fs/promises';
import * as Shared from '@cvmts/shared'; import * as Shared from '@cvmts/shared';
import { Socket, connect } from 'net'; import { Readable, Writable } from 'stream';
import { Readable, Stream, Writable } from 'stream';
export enum VMState { export enum VMState {
Stopped, Stopped,
@@ -24,6 +23,10 @@ export type QemuVmDefinition = {
/// Temporary path base (for UNIX sockets/etc.) /// Temporary path base (for UNIX sockets/etc.)
const kVmTmpPathBase = `/tmp`; const kVmTmpPathBase = `/tmp`;
// Test so I can test removing any (or well, the lone) sleep calls,
// in the qemuvm code.
const kTestDisableSleep = true;
// writer implementation for process standard I/O // writer implementation for process standard I/O
class StdioWriter implements IQmpClientWriter { class StdioWriter implements IQmpClientWriter {
stdout; stdout;
@@ -41,7 +44,8 @@ class StdioWriter implements IQmpClientWriter {
} }
writeSome(buffer: Buffer) { writeSome(buffer: Buffer) {
this.stdin.write(buffer); if(!this.stdin.closed)
this.stdin.write(buffer);
} }
} }
@@ -82,9 +86,9 @@ export class QemuVM extends EventEmitter {
self.display?.on('connected', () => { self.display?.on('connected', () => {
// The VM can now be considered started // The VM can now be considered started
self.VMLog().Info("Display connected"); self.VMLog().Info('Display connected');
self.SetState(VMState.Started); self.SetState(VMState.Started);
}) });
// now that QMP has connected, connect to the display // now that QMP has connected, connect to the display
self.display?.Connect(); self.display?.Connect();
@@ -232,8 +236,9 @@ export class QemuVM extends EventEmitter {
if (self.state != VMState.Stopping) { if (self.state != VMState.Stopping) {
if (code == 0) { if (code == 0) {
// Wait a bit and restart QEMU. if(!kTestDisableSleep)
await Shared.Sleep(500); await Shared.Sleep(500);
await self.StartQemu(split); await self.StartQemu(split);
} else { } else {
self.VMLog().Error('QEMU exited with a non-zero exit code. This usually means an error in the command line. Stopping VM.'); self.VMLog().Error('QEMU exited with a non-zero exit code. This usually means an error in the command line. Stopping VM.');
@@ -258,7 +263,7 @@ export class QemuVM extends EventEmitter {
private async QmpStdioInit() { private async QmpStdioInit() {
let self = this; let self = this;
self.VMLog().Info("Initializing QMP over stdio"); self.VMLog().Info('Initializing QMP over stdio');
// Setup the QMP client. // Setup the QMP client.
let writer = new StdioWriter(this.qemuProcess?.stdout!, this.qemuProcess?.stdin!, self.qmpInstance); let writer = new StdioWriter(this.qemuProcess?.stdout!, this.qemuProcess?.stdin!, self.qmpInstance);