Merge pull request #555 from ylei-tsubame/suiapi-rhel9-crash

Web UI: patch repeated SIGTERM on `anvil-access-module` child process
main
Digimer 12 months ago committed by GitHub
commit 56a9916909
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      striker-ui-api/out/index.js
  2. 39
      striker-ui-api/src/lib/accessModule.ts
  3. 7
      striker-ui-api/src/lib/consts/ENV.ts
  4. 9
      striker-ui-api/src/lib/repeat.ts
  5. 6
      striker-ui-api/src/types/AccessModule.d.ts
  6. 2
      striker-ui-api/webpack.config.js

File diff suppressed because one or more lines are too long

@ -1,16 +1,18 @@
import { ChildProcess, spawn, SpawnOptions } from 'child_process'; import { ChildProcess, spawn } from 'child_process';
import EventEmitter from 'events'; import EventEmitter from 'events';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import { import {
SERVER_PATHS, DEFAULT_JOB_PROGRESS,
DEBUG_ACCESS,
PGID, PGID,
PUID, PUID,
DEFAULT_JOB_PROGRESS,
REP_UUID, REP_UUID,
SERVER_PATHS,
} from './consts'; } from './consts';
import { formatSql } from './formatSql'; import { formatSql } from './formatSql';
import { repeat } from './repeat';
import { import {
date, date,
stderr as sherr, stderr as sherr,
@ -24,9 +26,13 @@ import {
* * This daemon's lifecycle events should follow the naming from systemd. * * This daemon's lifecycle events should follow the naming from systemd.
*/ */
class Access extends EventEmitter { class Access extends EventEmitter {
private static readonly VERBOSE: string = repeat('v', DEBUG_ACCESS, {
prefix: '-',
});
private ps: ChildProcess; private ps: ChildProcess;
private readonly mapToExternalEventHandler: Record< private readonly MAP_TO_EVT_HDL: Record<
string, string,
(args: { options: AccessStartOptions; ps: ChildProcess }) => void (args: { options: AccessStartOptions; ps: ChildProcess }) => void
> = { > = {
@ -42,22 +48,27 @@ class Access extends EventEmitter {
constructor({ constructor({
eventEmitterOptions = {}, eventEmitterOptions = {},
spawnOptions = {}, startOptions = {},
}: { }: {
eventEmitterOptions?: ConstructorParameters<typeof EventEmitter>[0]; eventEmitterOptions?: ConstructorParameters<typeof EventEmitter>[0];
spawnOptions?: SpawnOptions; startOptions?: AccessStartOptions;
} = {}) { } = {}) {
super(eventEmitterOptions); super(eventEmitterOptions);
this.ps = this.start(spawnOptions); const { args: initial = [], ...rest } = startOptions;
const args = [...initial, '--emit-events', Access.VERBOSE].filter(
(value) => value !== '',
);
this.ps = this.start({ args, ...rest });
} }
private start({ private start({
args = ['--emit-events'], args = [],
gid = PGID, gid = PGID,
restartInterval = 10000, restartInterval = 10000,
stdio = 'pipe', stdio = 'pipe',
timeout = 10000,
uid = PUID, uid = PUID,
...restSpawnOptions ...restSpawnOptions
}: AccessStartOptions = {}) { }: AccessStartOptions = {}) {
@ -66,7 +77,6 @@ class Access extends EventEmitter {
gid, gid,
restartInterval, restartInterval,
stdio, stdio,
timeout,
uid, uid,
...restSpawnOptions, ...restSpawnOptions,
}; };
@ -76,7 +86,6 @@ class Access extends EventEmitter {
const ps = spawn(SERVER_PATHS.usr.sbin['anvil-access-module'].self, args, { const ps = spawn(SERVER_PATHS.usr.sbin['anvil-access-module'].self, args, {
gid, gid,
stdio, stdio,
timeout,
uid, uid,
...restSpawnOptions, ...restSpawnOptions,
}); });
@ -115,7 +124,7 @@ class Access extends EventEmitter {
const { 1: n = '', 2: event } = parts; const { 1: n = '', 2: event } = parts;
this.mapToExternalEventHandler[event]?.call(null, { options, ps }); this.MAP_TO_EVT_HDL[event]?.call(null, { options, ps });
return n; return n;
}); });
@ -190,21 +199,17 @@ class Access extends EventEmitter {
} }
const access = new Access(); const access = new Access();
const rootAccess = new Access({ spawnOptions: { gid: 0, uid: 0 } });
const subroutine = async <T extends unknown[]>( const subroutine = async <T extends unknown[]>(
subroutine: string, subroutine: string,
{ {
params = [], params = [],
pre = ['Database'], pre = ['Database'],
root,
}: { }: {
params?: unknown[]; params?: unknown[];
pre?: string[]; pre?: string[];
root?: boolean;
} = {}, } = {},
) => { ) => {
const selectedAccess = root ? rootAccess : access;
const chain = `${pre.join('->')}->${subroutine}`; const chain = `${pre.join('->')}->${subroutine}`;
const subParams: string[] = params.map<string>((p) => { const subParams: string[] = params.map<string>((p) => {
@ -219,7 +224,7 @@ const subroutine = async <T extends unknown[]>(
return `"${result.replaceAll('"', '\\"')}"`; return `"${result.replaceAll('"', '\\"')}"`;
}); });
const { sub_results: results } = await selectedAccess.interact<{ const { sub_results: results } = await access.interact<{
sub_results: T; sub_results: T;
}>('x', chain, ...subParams); }>('x', chain, ...subParams);

@ -15,6 +15,13 @@ export const COOKIE_PREFIX = process.env.COOKIE_PREFIX ?? 'suiapi';
export const COOKIE_ORIGINAL_MAX_AGE: number = export const COOKIE_ORIGINAL_MAX_AGE: number =
Number(process.env.COOKIE_ORIGINAL_MAX_AGE) || 28800000; Number(process.env.COOKIE_ORIGINAL_MAX_AGE) || 28800000;
/**
* The debug level to pass to anvil-access-module; 1 is '-v', 2 is '-vv', ...
*
* @default 0
*/
export const DEBUG_ACCESS = Number(process.env.DEBUG_ACCESS) || 0;
/** /**
* The fallback job progress value when queuing jobs. * The fallback job progress value when queuing jobs.
* *

@ -0,0 +1,9 @@
export const repeat = (
value: string,
count: number,
{ prefix = '' }: { prefix?: string } = {},
): string => {
const repeated = value.repeat(count);
return repeated ? `${prefix}${repeated}` : '';
};

@ -1,3 +1,9 @@
/**
* Notes:
* - Option `timeout` for child_process.spawn was added in node15.13.0 to limit
* the lifespan of the child process; this is **not** the max wait time before
* the child process starts successfully.
*/
type AccessStartOptions = { type AccessStartOptions = {
args?: readonly string[]; args?: readonly string[];
restartInterval?: number; restartInterval?: number;

@ -32,5 +32,5 @@ module.exports = {
extensions: ['.js', '.ts'], extensions: ['.js', '.ts'],
}, },
stats: 'detailed', stats: 'detailed',
target: 'node10', target: ['node10', 'node16'],
}; };

Loading…
Cancel
Save