mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-29 19:21:33 -07:00
fix(anki,appimage): handle proxy port conflicts and stray GPU child
- AnkiConnect proxy now detects EADDRINUSE, logs a warning, and surfaces an overlay notification instead of crashing video startup - Background AppImage bootstrap runs Chromium with in-process-gpu so no GPU child survives app.exit() and outlives the FUSE mount, fixing the remaining DrKonqi "Service Crash" case - Add changelog fragment for the proxy fix; update the AppImage quit fragment with the GPU child root cause
This commit is contained in:
@@ -543,3 +543,41 @@ test('proxy detects self-referential loop configuration', () => {
|
||||
|
||||
assert.equal(result, true);
|
||||
});
|
||||
|
||||
test('proxy continues without a local listener when its address is already bound', async () => {
|
||||
const occupiedServer = http.createServer();
|
||||
occupiedServer.listen(0, '127.0.0.1');
|
||||
await once(occupiedServer, 'listening');
|
||||
const occupiedAddress = occupiedServer.address();
|
||||
assert.ok(occupiedAddress && typeof occupiedAddress === 'object');
|
||||
const info: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
const proxy = new AnkiConnectProxyServer({
|
||||
shouldAutoUpdateNewCards: () => true,
|
||||
processNewCard: async () => undefined,
|
||||
logInfo: (message) => info.push(message),
|
||||
logWarn: (message, ...args) => warnings.push([message, ...args].join(' ')),
|
||||
logError: () => undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
proxy.start({
|
||||
host: '127.0.0.1',
|
||||
port: occupiedAddress.port,
|
||||
upstreamUrl: 'http://127.0.0.1:8765',
|
||||
});
|
||||
|
||||
await proxy.waitUntilReady();
|
||||
|
||||
assert.equal(proxy.isRunning, false);
|
||||
assert.deepEqual(warnings, [
|
||||
`[anki-proxy] Local proxy unavailable because http://127.0.0.1:${occupiedAddress.port} is already in use; continuing without it. Change ankiConnect.proxy.port or stop the process using that address.`,
|
||||
]);
|
||||
proxy.stop();
|
||||
assert.deepEqual(info, []);
|
||||
} finally {
|
||||
proxy.stop();
|
||||
occupiedServer.close();
|
||||
await once(occupiedServer, 'close');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ export interface AnkiConnectProxyServerDeps {
|
||||
logInfo: (message: string, ...args: unknown[]) => void;
|
||||
logWarn: (message: string, ...args: unknown[]) => void;
|
||||
logError: (message: string, ...args: unknown[]) => void;
|
||||
notifyUnavailable?: (message: string) => void;
|
||||
}
|
||||
|
||||
export class AnkiConnectProxyServer {
|
||||
@@ -78,7 +79,23 @@ export class AnkiConnectProxyServer {
|
||||
void this.handleRequest(req, res, options.upstreamUrl);
|
||||
});
|
||||
|
||||
const server = this.server;
|
||||
this.server.on('error', (error) => {
|
||||
if ((error as NodeJS.ErrnoException).code === 'EADDRINUSE') {
|
||||
this.resolveReady?.();
|
||||
this.resolveReady = null;
|
||||
this.rejectReady = null;
|
||||
if (this.server === server) {
|
||||
this.server = null;
|
||||
}
|
||||
this.deps.logWarn(
|
||||
`[anki-proxy] Local proxy unavailable because http://${options.host}:${options.port} is already in use; continuing without it. Change ankiConnect.proxy.port or stop the process using that address.`,
|
||||
);
|
||||
this.deps.notifyUnavailable?.(
|
||||
`AnkiConnect proxy unavailable because http://${options.host}:${options.port} is already in use. Change ankiConnect.proxy.port or stop the process using that address.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.rejectReady?.(error as Error);
|
||||
this.resolveReady = null;
|
||||
this.rejectReady = null;
|
||||
|
||||
Reference in New Issue
Block a user