Skip to content

Commit 2527413

Browse files
committed
fix: pipe error logs in inspect gpu command
1 parent d53a07e commit 2527413

File tree

4 files changed

+90
-16
lines changed

4 files changed

+90
-16
lines changed

src/bindings/Llama.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {BindingModule} from "./AddonTypes.js";
1414
import {BuildGpu, BuildMetadataFile, LlamaGpuType, LlamaLocks, LlamaLogLevel, LlamaLogLevelGreaterThanOrEqual} from "./types.js";
1515
import {MemoryOrchestrator, MemoryReservation} from "./utils/MemoryOrchestrator.js";
1616

17-
const LlamaLogLevelToAddonLogLevel: ReadonlyMap<LlamaLogLevel, number> = new Map([
17+
export const LlamaLogLevelToAddonLogLevel: ReadonlyMap<LlamaLogLevel, number> = new Map([
1818
[LlamaLogLevel.disabled, 0],
1919
[LlamaLogLevel.fatal, 1],
2020
[LlamaLogLevel.error, 2],

src/bindings/getLlama.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,12 @@ export async function getLlamaForOptions({
342342
debug = defaultLlamaCppDebugMode
343343
}: LlamaOptions, {
344344
updateLastBuildInfoOnCompile = false,
345-
skipLlamaInit = false
345+
skipLlamaInit = false,
346+
pipeBinaryTestErrorLogs = false
346347
}: {
347348
updateLastBuildInfoOnCompile?: boolean,
348-
skipLlamaInit?: boolean
349+
skipLlamaInit?: boolean,
350+
pipeBinaryTestErrorLogs?: boolean
349351
} = {}): Promise<Llama> {
350352
const platform = getPlatform();
351353
const arch = process.arch;
@@ -463,7 +465,8 @@ export async function getLlamaForOptions({
463465
? "falling back to building from source"
464466
: null
465467
),
466-
debug
468+
debug,
469+
pipeBinaryTestErrorLogs
467470
});
468471

469472
if (llama != null)
@@ -556,7 +559,8 @@ async function loadExistingLlamaBinary({
556559
vramPadding,
557560
ramPadding,
558561
fallbackMessage,
559-
debug
562+
debug,
563+
pipeBinaryTestErrorLogs
560564
}: {
561565
buildOptions: BuildOptions,
562566
canUsePrebuiltBinaries: boolean,
@@ -571,7 +575,8 @@ async function loadExistingLlamaBinary({
571575
vramPadding: Required<LlamaOptions>["vramPadding"],
572576
ramPadding: Required<LlamaOptions>["ramPadding"],
573577
fallbackMessage: string | null,
574-
debug: boolean
578+
debug: boolean,
579+
pipeBinaryTestErrorLogs: boolean
575580
}) {
576581
const buildFolderName = await getBuildFolderNameForBuildOptions(buildOptions);
577582

@@ -590,7 +595,7 @@ async function loadExistingLlamaBinary({
590595
});
591596
const resolvedBindingPath = await resolveActualBindingBinaryPath(localBuildBinPath);
592597
const binaryCompatible = shouldTestBinaryBeforeLoading
593-
? await testBindingBinary(resolvedBindingPath, buildOptions.gpu)
598+
? await testBindingBinary(resolvedBindingPath, buildOptions.gpu, undefined, pipeBinaryTestErrorLogs)
594599
: true;
595600

596601
if (binaryCompatible) {
@@ -649,7 +654,7 @@ async function loadExistingLlamaBinary({
649654
});
650655
const resolvedBindingPath = await resolveActualBindingBinaryPath(prebuiltBinDetails.binaryPath);
651656
const binaryCompatible = shouldTestBinaryBeforeLoading
652-
? await testBindingBinary(resolvedBindingPath, buildOptions.gpu)
657+
? await testBindingBinary(resolvedBindingPath, buildOptions.gpu, undefined, pipeBinaryTestErrorLogs)
653658
: true;
654659

655660
if (binaryCompatible) {

src/bindings/utils/testBindingBinary.ts

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@ import {createRequire} from "module";
44
import path from "path";
55
import {getConsoleLogPrefix} from "../../utils/getConsoleLogPrefix.js";
66
import {runningInElectron} from "../../utils/runtime.js";
7-
import {BuildGpu} from "../types.js";
7+
import {BuildGpu, LlamaLogLevel} from "../types.js";
8+
import {LlamaLogLevelToAddonLogLevel} from "../Llama.js";
89
import type {BindingModule} from "../AddonTypes.js";
910

1011
const require = createRequire(import.meta.url);
1112
const __filename = fileURLToPath(import.meta.url);
1213
const detectedFileName = path.basename(__filename);
1314
const expectedFileName = "testBindingBinary";
1415

15-
export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu, testTimeout: number = 1000 * 60 * 5): Promise<boolean> {
16+
export async function testBindingBinary(
17+
bindingBinaryPath: string,
18+
gpu: BuildGpu,
19+
testTimeout: number = 1000 * 60 * 5,
20+
pipeOutputOnNode: boolean = false
21+
): Promise<boolean> {
1622
if (!detectedFileName.startsWith(expectedFileName)) {
1723
console.warn(
1824
getConsoleLogPrefix() +
@@ -57,7 +63,8 @@ export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu
5763
onExit(code: number): void
5864
}): {
5965
sendMessage(message: ParentToChildMessage): void,
60-
killProcess(): void
66+
killProcess(): void,
67+
pipeMessages(): void
6168
} {
6269
if (forkFunction.type === "electron") {
6370
let exited = false;
@@ -88,20 +95,28 @@ export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu
8895

8996
return {
9097
sendMessage: (message: ParentToChildMessage) => subProcess.postMessage(message),
91-
killProcess: cleanupElectronFork
98+
killProcess: cleanupElectronFork,
99+
pipeMessages: () => void 0
92100
};
93101
}
94102

103+
let pipeSet = false;
95104
const subProcess = forkFunction.fork(__filename, [], {
96105
detached: false,
97106
silent: true,
107+
stdio: pipeOutputOnNode
108+
? ["ignore", "pipe", "pipe", "ipc"]
109+
: ["ignore", "ignore", "ignore", "ipc"],
98110
env: {
99111
...process.env,
100112
TEST_BINDING_CP: "true"
101113
}
102114
});
103115

104116
function cleanupNodeFork() {
117+
subProcess.stdout?.off("data", onStdout);
118+
subProcess.stderr?.off("data", onStderr);
119+
105120
if (subProcess.exitCode == null)
106121
subProcess.kill("SIGKILL");
107122

@@ -121,9 +136,36 @@ export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu
121136
onExit(subProcess.exitCode ?? -1);
122137
}
123138

139+
function onStdout(data: string) {
140+
if (!pipeSet)
141+
return;
142+
143+
process.stdout.write(data);
144+
}
145+
146+
function onStderr(data: string) {
147+
if (!pipeSet)
148+
return;
149+
150+
process.stderr.write(data);
151+
}
152+
153+
if (pipeOutputOnNode) {
154+
subProcess.stdout?.on("data", onStdout);
155+
subProcess.stderr?.on("data", onStderr);
156+
}
157+
158+
function pipeMessages() {
159+
if (!pipeOutputOnNode || pipeSet)
160+
return;
161+
162+
pipeSet = true;
163+
}
164+
124165
return {
125166
sendMessage: (message: ParentToChildMessage) => subProcess.send(message),
126-
killProcess: cleanupNodeFork
167+
killProcess: cleanupNodeFork,
168+
pipeMessages
127169
};
128170
}
129171

@@ -169,6 +211,13 @@ export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu
169211
bindingBinaryPath,
170212
gpu
171213
});
214+
} else if (message.type === "loaded") {
215+
subProcess!.pipeMessages(); // only start piping error logs if the binary loaded successfully
216+
subProcess!.sendMessage({
217+
type: "test",
218+
bindingBinaryPath,
219+
gpu
220+
});
172221
} else if (message.type === "done") {
173222
testPassed = true;
174223
subProcess!.sendMessage({type: "exit"});
@@ -189,13 +238,28 @@ export async function testBindingBinary(bindingBinaryPath: string, gpu: BuildGpu
189238
}
190239

191240
if (process.env.TEST_BINDING_CP === "true" && (process.parentPort != null || process.send != null)) {
241+
let binding: BindingModule;
192242
const sendMessage = process.parentPort != null
193243
? (message: ChildToParentMessage) => process.parentPort.postMessage(message)
194244
: (message: ChildToParentMessage) => process.send!(message);
195245
const onMessage = async (message: ParentToChildMessage) => {
196246
if (message.type === "start") {
197247
try {
198-
const binding: BindingModule = require(message.bindingBinaryPath);
248+
binding = require(message.bindingBinaryPath);
249+
250+
const errorLogLevel = LlamaLogLevelToAddonLogLevel.get(LlamaLogLevel.error);
251+
if (errorLogLevel != null)
252+
binding.setLoggerLogLevel(errorLogLevel);
253+
254+
sendMessage({type: "loaded"});
255+
} catch (err) {
256+
console.error(err);
257+
process.exit(1);
258+
}
259+
} else if (message.type === "test") {
260+
try {
261+
if (binding == null)
262+
throw new Error("Binding binary is not loaded");
199263

200264
binding.loadBackends();
201265
const loadedGpu = binding.getGpuType();
@@ -235,9 +299,13 @@ type ParentToChildMessage = {
235299
type: "start",
236300
bindingBinaryPath: string,
237301
gpu: BuildGpu
302+
} | {
303+
type: "test",
304+
bindingBinaryPath: string,
305+
gpu: BuildGpu
238306
} | {
239307
type: "exit"
240308
};
241309
type ChildToParentMessage = {
242-
type: "ready" | "done"
310+
type: "ready" | "loaded" | "done"
243311
};

src/cli/commands/inspect/commands/InspectGpuCommand.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ async function getLlamaForGpu(gpu: BuildGpu) {
172172
logLevel: LlamaLogLevel.warn,
173173
vramPadding: 0
174174
}, {
175-
skipLlamaInit: true
175+
skipLlamaInit: true,
176+
pipeBinaryTestErrorLogs: true
176177
});
177178
} catch (err) {
178179
return undefined;

0 commit comments

Comments
 (0)