Skip to content

Commit 56a9916

Browse files
authored
Merge pull request #555 from ylei-tsubame/suiapi-rhel9-crash
Web UI: patch repeated SIGTERM on `anvil-access-module` child process
2 parents 3438186 + 3033f50 commit 56a9916

File tree

6 files changed

+46
-19
lines changed

6 files changed

+46
-19
lines changed

striker-ui-api/out/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

striker-ui-api/src/lib/accessModule.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { ChildProcess, spawn, SpawnOptions } from 'child_process';
1+
import { ChildProcess, spawn } from 'child_process';
22
import EventEmitter from 'events';
33
import { readFileSync } from 'fs';
44

55
import {
6-
SERVER_PATHS,
6+
DEFAULT_JOB_PROGRESS,
7+
DEBUG_ACCESS,
78
PGID,
89
PUID,
9-
DEFAULT_JOB_PROGRESS,
1010
REP_UUID,
11+
SERVER_PATHS,
1112
} from './consts';
1213

1314
import { formatSql } from './formatSql';
15+
import { repeat } from './repeat';
1416
import {
1517
date,
1618
stderr as sherr,
@@ -24,9 +26,13 @@ import {
2426
* * This daemon's lifecycle events should follow the naming from systemd.
2527
*/
2628
class Access extends EventEmitter {
29+
private static readonly VERBOSE: string = repeat('v', DEBUG_ACCESS, {
30+
prefix: '-',
31+
});
32+
2733
private ps: ChildProcess;
2834

29-
private readonly mapToExternalEventHandler: Record<
35+
private readonly MAP_TO_EVT_HDL: Record<
3036
string,
3137
(args: { options: AccessStartOptions; ps: ChildProcess }) => void
3238
> = {
@@ -42,22 +48,27 @@ class Access extends EventEmitter {
4248

4349
constructor({
4450
eventEmitterOptions = {},
45-
spawnOptions = {},
51+
startOptions = {},
4652
}: {
4753
eventEmitterOptions?: ConstructorParameters<typeof EventEmitter>[0];
48-
spawnOptions?: SpawnOptions;
54+
startOptions?: AccessStartOptions;
4955
} = {}) {
5056
super(eventEmitterOptions);
5157

52-
this.ps = this.start(spawnOptions);
58+
const { args: initial = [], ...rest } = startOptions;
59+
60+
const args = [...initial, '--emit-events', Access.VERBOSE].filter(
61+
(value) => value !== '',
62+
);
63+
64+
this.ps = this.start({ args, ...rest });
5365
}
5466

5567
private start({
56-
args = ['--emit-events'],
68+
args = [],
5769
gid = PGID,
5870
restartInterval = 10000,
5971
stdio = 'pipe',
60-
timeout = 10000,
6172
uid = PUID,
6273
...restSpawnOptions
6374
}: AccessStartOptions = {}) {
@@ -66,7 +77,6 @@ class Access extends EventEmitter {
6677
gid,
6778
restartInterval,
6879
stdio,
69-
timeout,
7080
uid,
7181
...restSpawnOptions,
7282
};
@@ -76,7 +86,6 @@ class Access extends EventEmitter {
7686
const ps = spawn(SERVER_PATHS.usr.sbin['anvil-access-module'].self, args, {
7787
gid,
7888
stdio,
79-
timeout,
8089
uid,
8190
...restSpawnOptions,
8291
});
@@ -115,7 +124,7 @@ class Access extends EventEmitter {
115124

116125
const { 1: n = '', 2: event } = parts;
117126

118-
this.mapToExternalEventHandler[event]?.call(null, { options, ps });
127+
this.MAP_TO_EVT_HDL[event]?.call(null, { options, ps });
119128

120129
return n;
121130
});
@@ -190,21 +199,17 @@ class Access extends EventEmitter {
190199
}
191200

192201
const access = new Access();
193-
const rootAccess = new Access({ spawnOptions: { gid: 0, uid: 0 } });
194202

195203
const subroutine = async <T extends unknown[]>(
196204
subroutine: string,
197205
{
198206
params = [],
199207
pre = ['Database'],
200-
root,
201208
}: {
202209
params?: unknown[];
203210
pre?: string[];
204-
root?: boolean;
205211
} = {},
206212
) => {
207-
const selectedAccess = root ? rootAccess : access;
208213
const chain = `${pre.join('->')}->${subroutine}`;
209214

210215
const subParams: string[] = params.map<string>((p) => {
@@ -219,7 +224,7 @@ const subroutine = async <T extends unknown[]>(
219224
return `"${result.replaceAll('"', '\\"')}"`;
220225
});
221226

222-
const { sub_results: results } = await selectedAccess.interact<{
227+
const { sub_results: results } = await access.interact<{
223228
sub_results: T;
224229
}>('x', chain, ...subParams);
225230

striker-ui-api/src/lib/consts/ENV.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ export const COOKIE_PREFIX = process.env.COOKIE_PREFIX ?? 'suiapi';
1515
export const COOKIE_ORIGINAL_MAX_AGE: number =
1616
Number(process.env.COOKIE_ORIGINAL_MAX_AGE) || 28800000;
1717

18+
/**
19+
* The debug level to pass to anvil-access-module; 1 is '-v', 2 is '-vv', ...
20+
*
21+
* @default 0
22+
*/
23+
export const DEBUG_ACCESS = Number(process.env.DEBUG_ACCESS) || 0;
24+
1825
/**
1926
* The fallback job progress value when queuing jobs.
2027
*

striker-ui-api/src/lib/repeat.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const repeat = (
2+
value: string,
3+
count: number,
4+
{ prefix = '' }: { prefix?: string } = {},
5+
): string => {
6+
const repeated = value.repeat(count);
7+
8+
return repeated ? `${prefix}${repeated}` : '';
9+
};

striker-ui-api/src/types/AccessModule.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Notes:
3+
* - Option `timeout` for child_process.spawn was added in node15.13.0 to limit
4+
* the lifespan of the child process; this is **not** the max wait time before
5+
* the child process starts successfully.
6+
*/
17
type AccessStartOptions = {
28
args?: readonly string[];
39
restartInterval?: number;

striker-ui-api/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ module.exports = {
3232
extensions: ['.js', '.ts'],
3333
},
3434
stats: 'detailed',
35-
target: 'node10',
35+
target: ['node10', 'node16'],
3636
};

0 commit comments

Comments
 (0)