🐛 fix(vscode): 完成列/删 worktree 时自动杀掉占用进程再删目录
This commit is contained in:
@@ -110,10 +110,8 @@ export interface WorktreeProcHit {
|
||||
/**
|
||||
* 扫 /proc 找出 cwd 或打开的 fd 落在 worktree 目录(含子目录)下的进程。
|
||||
*
|
||||
* 删 worktree 前的守门:dev server(pnpm dev / vite / next dev)常驻在 worktree
|
||||
* 里持续往构建产物目录写文件,此时递归删除会与写入竞态——rm 删完子项后 rmdir
|
||||
* 父目录,进程刚好又塞进新文件 → ENOTEMPTY。force:true 只免疫「文件不存在」,
|
||||
* 救不了「删除期间目录被重新填充」。所以占用就别删,交给用户先停进程。
|
||||
* 扫占用 worktree 的进程。dev server 等常驻进程会让递归删除撞 ENOTEMPTY
|
||||
* (删期间目录被重新填充);调用方应先 killProcessesUsingWorktree 再删。
|
||||
*
|
||||
* 非 Linux(无 /proc)返回空数组 → 调用方降级为直接删除。
|
||||
*/
|
||||
@@ -166,3 +164,50 @@ export function findProcessesUsingWorktree(absWorktreePath: string): WorktreePro
|
||||
}
|
||||
return hits
|
||||
}
|
||||
|
||||
/**
|
||||
* 删 worktree 前杀掉占用目录的进程(SIGTERM → 短暂等待 → SIGKILL)。
|
||||
*
|
||||
* 跳过 process.pid / process.ppid,避免误杀扩展宿主或父 VS Code。
|
||||
* 非 Linux(find 返回空)为 no-op。返回被尝试杀掉的 hits,供调用方记日志。
|
||||
*/
|
||||
export function killProcessesUsingWorktree(absWorktreePath: string): WorktreeProcHit[] {
|
||||
const selfPid = String(process.pid)
|
||||
const parentPid = String(process.ppid)
|
||||
// ① 扫占用 → 过滤掉自身/父进程
|
||||
const hits = findProcessesUsingWorktree(absWorktreePath)
|
||||
.filter(h => h.pid !== selfPid && h.pid !== parentPid)
|
||||
if (hits.length === 0)
|
||||
return hits
|
||||
|
||||
// ② SIGTERM 温和退出(ESRCH=已死 → 忽略)
|
||||
for (const h of hits) {
|
||||
try {
|
||||
process.kill(Number(h.pid), 'SIGTERM')
|
||||
}
|
||||
catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code
|
||||
if (code !== 'ESRCH')
|
||||
console.warn(`[superpowers] SIGTERM pid ${h.pid} 失败:`, err)
|
||||
}
|
||||
}
|
||||
|
||||
// ③ 同步等 ~400ms,给 dev server 关句柄的时间
|
||||
const sab = new SharedArrayBuffer(4)
|
||||
const ia = new Int32Array(sab)
|
||||
Atomics.wait(ia, 0, 0, 400)
|
||||
|
||||
// ④ 仍存活的 SIGKILL 兜底
|
||||
for (const h of hits) {
|
||||
try {
|
||||
process.kill(Number(h.pid), 0) // 探测是否仍在
|
||||
process.kill(Number(h.pid), 'SIGKILL')
|
||||
}
|
||||
catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code
|
||||
if (code !== 'ESRCH')
|
||||
console.warn(`[superpowers] SIGKILL pid ${h.pid} 失败:`, err)
|
||||
}
|
||||
}
|
||||
return hits
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user