Skip to content

Commit c70efab

Browse files
authoredJul 2, 2024··
Merge pull request #392 from crazy-max/history-export-detach-dialstdio
buildx(history): detach dial-stdio process
2 parents 55a2181 + ff35e30 commit c70efab

File tree

1 file changed

+48
-17
lines changed

1 file changed

+48
-17
lines changed
 

‎src/buildx/history.ts

+48-17
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
import {ChildProcessByStdio, spawn} from 'child_process';
1818
import fs from 'fs';
19-
import {Readable, Writable} from 'node:stream';
2019
import os from 'os';
2120
import path from 'path';
21+
import {Readable, Writable} from 'stream';
2222
import * as core from '@actions/core';
2323

2424
import {Buildx} from './buildx';
@@ -92,14 +92,29 @@ export class History {
9292
});
9393
await Exec.exec('mkfifo', [buildxOutFifoPath]);
9494

95-
const buildxCmd = await this.buildx.getCommand(['--builder', builderName, 'dial-stdio']);
96-
const buildxDialStdioProc = History.spawn(buildxCmd.command, buildxCmd.args);
95+
const buildxDialStdioCmd = await this.buildx.getCommand(['--builder', builderName, 'dial-stdio']);
96+
core.info(`[command]${buildxDialStdioCmd.command} ${buildxDialStdioCmd.args.join(' ')}`);
97+
const buildxDialStdioProc = spawn(buildxDialStdioCmd.command, buildxDialStdioCmd.args, {
98+
stdio: ['pipe', 'pipe', 'inherit'],
99+
detached: true
100+
});
101+
let buildxDialStdioKilled = false;
97102
fs.createReadStream(buildxInFifoPath).pipe(buildxDialStdioProc.stdin);
98103
buildxDialStdioProc.stdout.pipe(fs.createWriteStream(buildxOutFifoPath));
104+
buildxDialStdioProc.on('exit', (code, signal) => {
105+
buildxDialStdioKilled = true;
106+
if (signal) {
107+
core.info(`Process "buildx dial-stdio" was killed with signal ${signal}`);
108+
} else {
109+
core.info(`Process "buildx dial-stdio" exited with code ${code}`);
110+
}
111+
});
99112

100113
const tmpDockerbuildFilename = path.join(outDir, 'rec.dockerbuild');
101114
const summaryFilename = path.join(outDir, 'summary.json');
102115

116+
let dockerRunProc: ChildProcessByStdio<Writable, Readable, null> | undefined;
117+
let dockerRunProcKilled = false;
103118
await new Promise<void>((resolve, reject) => {
104119
const ebargs: Array<string> = ['--ref-state-dir=/buildx-refs', `--node=${builderName}/${nodeName}`];
105120
for (const ref of refs) {
@@ -112,13 +127,17 @@ export class History {
112127
ebargs.push(`--gid=${process.getgid()}`);
113128
}
114129
// prettier-ignore
115-
const dockerRunProc = History.spawn('docker', [
130+
const dockerRunArgs = [
116131
'run', '--rm', '-i',
117132
'-v', `${Buildx.refsDir}:/buildx-refs`,
118133
'-v', `${outDir}:/out`,
119134
opts.image || History.EXPORT_TOOL_IMAGE,
120135
...ebargs
121-
]);
136+
]
137+
core.info(`[command]docker ${dockerRunArgs.join(' ')}`);
138+
dockerRunProc = spawn('docker', dockerRunArgs, {
139+
stdio: ['pipe', 'pipe', 'inherit']
140+
});
122141
fs.createReadStream(buildxOutFifoPath).pipe(dockerRunProc.stdin);
123142
dockerRunProc.stdout.pipe(fs.createWriteStream(buildxInFifoPath));
124143
dockerRunProc.on('close', code => {
@@ -129,16 +148,35 @@ export class History {
129148
resolve();
130149
}
131150
} else {
132-
reject(new Error(`Process "docker run" exited with code ${code}`));
151+
reject(new Error(`Process "docker run" closed with code ${code}`));
133152
}
134153
});
135154
dockerRunProc.on('error', err => {
136-
core.error(`Error executing buildx dial-stdio: ${err}`);
155+
core.error(`Error executing "docker run": ${err}`);
137156
reject(err);
138157
});
139-
}).catch(err => {
140-
throw err;
141-
});
158+
dockerRunProc.on('exit', (code, signal) => {
159+
dockerRunProcKilled = true;
160+
if (signal) {
161+
core.info(`Process "docker run" was killed with signal ${signal}`);
162+
} else {
163+
core.info(`Process "docker run" exited with code ${code}`);
164+
}
165+
});
166+
})
167+
.catch(err => {
168+
throw err;
169+
})
170+
.finally(() => {
171+
if (buildxDialStdioProc && !buildxDialStdioKilled) {
172+
core.debug('Force terminating "buildx dial-stdio" process');
173+
buildxDialStdioProc.kill('SIGKILL');
174+
}
175+
if (dockerRunProc && !dockerRunProcKilled) {
176+
core.debug('Force terminating "docker run" process');
177+
dockerRunProc.kill('SIGKILL');
178+
}
179+
});
142180

143181
let dockerbuildFilename = `${GitHub.context.repo.owner}~${GitHub.context.repo.repo}~${refs[0].substring(0, 6).toUpperCase()}`;
144182
if (refs.length > 1) {
@@ -162,11 +200,4 @@ export class History {
162200
refs: refs
163201
};
164202
}
165-
166-
private static spawn(command: string, args?: ReadonlyArray<string>): ChildProcessByStdio<Writable, Readable, null> {
167-
core.info(`[command]${command}${args ? ` ${args.join(' ')}` : ''}`);
168-
return spawn(command, args || [], {
169-
stdio: ['pipe', 'pipe', 'inherit']
170-
});
171-
}
172203
}

0 commit comments

Comments
 (0)
Please sign in to comment.