mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 06:28:59 +02:00
fix(setup): lock reclaim hands a fresh lock back; a live holder past the bound is stale; /proc walk strips through the last paren
- Reclaim renamed the lock by path after judging it stale, so a second setup that had already reclaimed and re-created it lost its fresh lock and two installers ran. After the rename the moved directory's pid is re-read: a new live holder, or a fresh lock whose pid is not written yet, is moved straight back. - A pid file whose process is alive but whose lock is older than the install bound is stale too (the holder is past its own deadline, or the pid was recycled to an unrelated long-lived process); it was locked forever. - The /proc fallback stripped the comm field to the FIRST ") ", so a comm containing ") " hid a child from the kill. proc(5) says the last paren. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
a8bc93eb2c
commit
8e1e520fe5
@@ -115,6 +115,7 @@ function runBlock(opts: {
|
||||
env?: Record<string, string>;
|
||||
preLockPid?: string; // pre-create the install lock held by this pid
|
||||
preLockNoPidAgeMin?: number; // pre-create a lock dir with NO pid file, this many minutes old
|
||||
preLockAgeMin?: number; // with preLockPid: age the lock dir this many minutes
|
||||
markKill?: boolean; // record _kill_tree invocations to $MARK
|
||||
isWindows?: '0' | '1';
|
||||
prelude?: string; // extra shell lines (node/npm stubs) injected before the block
|
||||
@@ -130,6 +131,10 @@ function runBlock(opts: {
|
||||
const lock = path.join(tmp, 'gstack-playwright-install.lock');
|
||||
fs.mkdirSync(lock);
|
||||
fs.writeFileSync(path.join(lock, 'pid'), opts.preLockPid);
|
||||
if (opts.preLockAgeMin !== undefined) {
|
||||
const t = new Date(Date.now() - opts.preLockAgeMin * 60_000);
|
||||
fs.utimesSync(lock, t, t);
|
||||
}
|
||||
}
|
||||
if (opts.preLockNoPidAgeMin !== undefined) {
|
||||
const lock = path.join(tmp, 'gstack-playwright-install.lock');
|
||||
@@ -237,6 +242,14 @@ describe('setup: Chromium bootstrap block executes best-effort', () => {
|
||||
}
|
||||
}, 15_000);
|
||||
|
||||
test('a lock held by a LIVE pid but older than the install bound is reclaimed (holder past its deadline, or a recycled pid)', () => {
|
||||
const r = runBlock({ probe: 'fail', bunx: 'exit 0', preLockPid: String(process.pid), preLockAgeMin: 30, env: { GSTACK_PLAYWRIGHT_INSTALL_TIMEOUT: '60' } });
|
||||
expect(r.status).toBe(0);
|
||||
expect(fs.readFileSync(path.join(r.tmp, 'mark'), 'utf-8')).toContain('bunx-called');
|
||||
expect(r.stdout).not.toContain('chromium-install-locked');
|
||||
expect(r.stderr).toContain('past the install bound');
|
||||
}, 15_000);
|
||||
|
||||
test('a lock dir with NO pid file is reclaimed once older than the install bound, and honored while fresh', () => {
|
||||
const old = runBlock({ probe: 'fail', bunx: 'exit 0', preLockNoPidAgeMin: 30, env: { GSTACK_PLAYWRIGHT_INSTALL_TIMEOUT: '60' } });
|
||||
expect(old.status).toBe(0);
|
||||
@@ -604,7 +617,7 @@ describe.skipIf(process.platform === 'win32')('setup: .gstack-owned ownership ma
|
||||
fs.writeFileSync(path.join(r.skills, 'my-own', 'SKILL.md'), '---\nname: my-own\n---\n');
|
||||
const flip = spawnSync('bash', ['-c', [
|
||||
'set -e', 'IS_WINDOWS=1',
|
||||
extractFn('_gstack_link_target_abs'), extractFn('_gstack_target_is_ours'), extractFn('_gstack_dir_only_links'), extractFn('_cleanup_linked_dir'), extractFn('_gstack_generated_header'), extractFn('_cleanup_weak_dir'),
|
||||
extractFn('_gstack_link_target_abs'), extractFn('_gstack_target_is_ours'), extractFn('_gstack_dir_only_links'), extractFn('_cleanup_linked_dir'), extractFn('_gstack_generated_header'), extractFn('_cleanup_weak_dir'), extractFn('_backup_skill_md'), '_BACKED_UP_SKILL_MDS=()', '_SKILL_BACKUP_ROOT="$HOME/.gstack/backups/skills/test"',
|
||||
extractFn('cleanup_old_claude_symlinks'),
|
||||
`cleanup_old_claude_symlinks "${r.payload}" "${r.skills}"`,
|
||||
].join('\n')], { encoding: 'utf-8', timeout: 10_000 });
|
||||
|
||||
Reference in New Issue
Block a user