mirror of
https://github.com/zhaoxuya520/reverse-skill.git
synced 2026-10-29 19:53:40 +08:00
fix(ida-reverse): deadlock on last-healthy, not process age
Keep-alive Force only after tools/list stays unhealthy >180s. open.ps1 holds opening.lock so in-flight idb_open is never replaced. GUI and never-healthy stay busy/reuse. recover.ps1 remains the manual -Force path.
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
||||
- **CI runs remaining unwired suites** — `test-p0-friction.ps1` on the Windows leg of `routing-tests` (Windows PowerShell 5.1); `case-review/tests/test_review_case.py` in the Linux `case-contract` job. `test-workflow-title-safety.ps1` was already wired.
|
||||
|
||||
### Fixed
|
||||
- **IDA MCP HTTP stall** — `run-supervisor.py` patches stock `idalib_supervisor` onto `ThreadingHTTPServer` and accepts Streamable HTTP GET `/mcp` (patch failure is skipped, supervisor still starts). `watchdog.ps1` / `start.ps1` replace a *managed* supervisor if `tools/list` stays dead for more than 3 minutes; GUI and in-flight `idb_open` stay busy/reuse. New `recover.ps1` is an immediate `-Force` path. Never `taskkill`s `ida.exe`.
|
||||
- **IDA MCP HTTP stall** — `run-supervisor.py` patches stock `idalib_supervisor` onto `ThreadingHTTPServer` and accepts Streamable HTTP GET `/mcp` (patch failure is skipped, supervisor still starts). Keep-alive deadlock is **time since last healthy `tools/list`**, not process `CreationDate`; `open.ps1` holds `opening.lock` so in-flight opens are never `-Force`d. New `recover.ps1` is an immediate `-Force` path. Never `taskkill`s `ida.exe`.
|
||||
- **Windows PowerShell 5.1 encoding** — added a UTF-8 BOM to five non-ASCII `.ps1` scripts (`skills/scripts/verify-doc-facts.ps1`, `apk-reverse/scripts/frida-run.ps1`, `apk-reverse/scripts/rebuild-sign-install.ps1`, `ida-reverse/scripts/start.ps1`, `radare2/scripts/recon.ps1`). Without a BOM, PS 5.1 parses these files as the system ANSI codepage and garbles their Chinese / em-dash string literals; `verify-doc-facts.ps1` was failing four checks under 5.1 (CI only ran it under `pwsh`, which defaults to UTF-8). CI now guards every non-ASCII `.ps1` for a BOM.
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -35,8 +35,8 @@ python -m ida_pro_mcp --install --transport streamable-http --scope global
|
||||
|
||||
| 脚本 | 作用 |
|
||||
|------|------|
|
||||
| `scripts/start.ps1` | 健康则 `OK:<n>:reuse`;端口在听但 RPC 超时视为忙,不杀;只在无人监听或缺 `py_eval` 时替换 managed supervisor;永不杀 `ida.exe` |
|
||||
| `scripts/watchdog.ps1` | 每分钟巡检;健康 reuse;GUI/新开库 busy reuse;**managed supervisor 超过 3 分钟仍答不上 tools/list 则 `-Force` 拉起** |
|
||||
| `scripts/start.ps1` | 健康则 `OK:<n>:reuse` 并刷新 last-healthy;端口在听但 RPC 超时视为忙,不杀;只在无人监听、缺 `py_eval`、或 tools/list 连续失败超过 3 分钟(且无 `opening.lock`)时替换 managed supervisor;永不杀 `ida.exe` |
|
||||
| `scripts/watchdog.ps1` | 每分钟巡检;健康 reuse;GUI / `open.ps1` 开库锁 / last-healthy 未满 3 分钟 → reuse;**tools/list 连续失败超过 3 分钟才 `-Force`** |
|
||||
| `scripts/recover.ps1` | 立刻 `-Force` 重启 supervisor(不杀 `ida.exe`)。HTTP 客户端把 `idapro` 标成 error 时用这个 |
|
||||
| `scripts/install-autostart.ps1` | 注册计划任务 `reverse-skill-ida-mcp`(登录 + 每分钟) |
|
||||
| `scripts/start-gui.ps1` | idalib license 失败时开 GUI 插件 |
|
||||
|
||||
@@ -56,8 +56,8 @@ description: |
|
||||
- 第一次 `open.ps1` 超时后,idalib 的 python worker 子进程可能变成孤儿,咬着 `.id0`/`.id1`/`.nam` 不放
|
||||
- 后续任何工具或手动拖入 IDA GUI 都会报"权限不足"
|
||||
- **禁止** `taskkill /F /T` 杀进程树——`/T` 会把 GUI `ida.exe` 子进程一起干掉
|
||||
- **解决办法**:`start.ps1` 只在端口无人监听、或 `tools/list` 快速返回但缺 `py_eval`(旧 supervisor)时替换 managed supervisor;RPC 超时且 13337 仍在听、且进程是 GUI 或开库未满 3 分钟,视为忙,不杀
|
||||
- **死锁例外**:managed supervisor 超过 3 分钟仍答不上 `tools/list` 时,`watchdog.ps1` / `start.ps1` 用 `-Force` 只替换 supervisor,仍不杀 `ida.exe`
|
||||
- **解决办法**:`start.ps1` 只在端口无人监听、或 `tools/list` 快速返回但缺 `py_eval`(旧 supervisor)时替换 managed supervisor;RPC 超时且 13337 仍在听视为忙,不杀。开库时 `open.ps1` 写 `opening.lock`,watchdog 不得 `-Force`
|
||||
- **死锁例外**:`tools/list` **连续失败超过 3 分钟**(按 last-healthy 时间戳,不是进程创建时间),且没有 in-flight `opening.lock`、不是 GUI 占端口时,才 `-Force` 替换 supervisor,仍不杀 `ida.exe`
|
||||
- **兜底**:`open.ps1` 检测到旧库被锁自动复制到 Temp 并加 GUID 前缀
|
||||
|
||||
8. **带自动分析打开看起来像卡死**
|
||||
@@ -96,7 +96,7 @@ description: |
|
||||
- 优先用 IDA 自带 `Python314\python.exe -m ida_pro_mcp.idalib_supervisor`
|
||||
- 默认先探测 `http://127.0.0.1:13337/mcp`,健康则输出 `OK:<n>:reuse` 并退出
|
||||
- 13337 在听但 `tools/list` 超时 → `WARN:busy` / `OK:busy:reuse`,**不杀**(开库或 GUI 占用时无法回包)
|
||||
- managed supervisor **超过 3 分钟**仍答不上 `tools/list` → 视为死锁,输出 `INFO:deadlock` 并 `-Force` 替换 supervisor
|
||||
- `tools/list` **连续失败超过 3 分钟**(last-healthy 时间戳)且无 `opening.lock` → 视为死锁,输出 `INFO:deadlock` 并 `-Force` 替换 supervisor。进行中的 `idb_open` 和 GUI 不会走这条路径
|
||||
- 仅在端口无人监听、缺 `py_eval`、或上述死锁时替换 managed supervisor;**永不杀 `ida.exe`,不用 `taskkill /T`**
|
||||
- GUI 占用 13337 时输出 `WARN:gui_busy` 并退出,不另起 supervisor
|
||||
- 成功输出 `OK:<工具数>`(当前约 66),失败输出 `ERR:timeout`
|
||||
@@ -110,7 +110,7 @@ powershell -File "<skill-root>\ida-reverse\scripts\start.ps1"
|
||||
|
||||
### watchdog.ps1 / recover.ps1 / install-autostart.ps1 — 保活
|
||||
|
||||
- `watchdog.ps1`:探测 13337;健康 reuse;GUI/新开库 busy reuse;managed supervisor 超过 3 分钟仍无 `tools/list` 则 `start.ps1 -Force`
|
||||
- `watchdog.ps1`:探测 13337;健康 reuse(并刷新 last-healthy);GUI / `open.ps1` 开库锁 / last-healthy 未满 3 分钟的 busy → reuse;只有 `tools/list` 连续失败超过 3 分钟才 `start.ps1 -Force`
|
||||
- `recover.ps1`:立刻 `start.ps1 -Force`(不杀 `ida.exe`)。HTTP 客户端把 `idapro` 标成 error 时用这个
|
||||
- `install-autostart.ps1`:注册计划任务 `reverse-skill-ida-mcp`(登录 + 每分钟)
|
||||
- 日志:`%LOCALAPPDATA%\reverse-skill\ida-mcp\watchdog.log`
|
||||
|
||||
@@ -26,3 +26,75 @@ function Get-IdaOpenLockPlan {
|
||||
PreferTempCopy = $hasLocked
|
||||
}
|
||||
}
|
||||
|
||||
function Get-IdaMcpKeepaliveDir {
|
||||
$dir = Join-Path $env:LOCALAPPDATA 'reverse-skill\ida-mcp'
|
||||
if (-not (Test-Path -LiteralPath $dir)) {
|
||||
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
||||
}
|
||||
return $dir
|
||||
}
|
||||
|
||||
function Get-IdaMcpLastHealthyPath {
|
||||
return Join-Path (Get-IdaMcpKeepaliveDir) 'last-healthy.txt'
|
||||
}
|
||||
|
||||
function Get-IdaMcpOpeningLockPath {
|
||||
return Join-Path (Get-IdaMcpKeepaliveDir) 'opening.lock'
|
||||
}
|
||||
|
||||
function Write-IdaMcpLastHealthy {
|
||||
Set-Content -LiteralPath (Get-IdaMcpLastHealthyPath) -Value 'ok' -Encoding ASCII
|
||||
}
|
||||
|
||||
function Read-IdaMcpLastHealthy {
|
||||
$path = Get-IdaMcpLastHealthyPath
|
||||
if (-not (Test-Path -LiteralPath $path)) { return $null }
|
||||
return (Get-Item -LiteralPath $path).LastWriteTime
|
||||
}
|
||||
|
||||
function Set-IdaMcpOpeningLock {
|
||||
param([int]$TtlSeconds = 600)
|
||||
$ttl = [Math]::Max(1, $TtlSeconds)
|
||||
$until = (Get-Date).AddSeconds($ttl).ToString('o')
|
||||
Set-Content -LiteralPath (Get-IdaMcpOpeningLockPath) -Value $until -Encoding ASCII
|
||||
}
|
||||
|
||||
function Clear-IdaMcpOpeningLock {
|
||||
$path = Get-IdaMcpOpeningLockPath
|
||||
if (Test-Path -LiteralPath $path) {
|
||||
Remove-Item -LiteralPath $path -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
function Test-IdaMcpOpeningInFlight {
|
||||
param([datetime]$Now = (Get-Date))
|
||||
$path = Get-IdaMcpOpeningLockPath
|
||||
if (-not (Test-Path -LiteralPath $path)) { return $false }
|
||||
$raw = (Get-Content -LiteralPath $path -Raw -ErrorAction SilentlyContinue)
|
||||
if ([string]::IsNullOrWhiteSpace($raw)) { return $true }
|
||||
try {
|
||||
$until = [datetime]::Parse($raw.Trim(), $null, [System.Globalization.DateTimeStyles]::RoundtripKind)
|
||||
} catch {
|
||||
return $true
|
||||
}
|
||||
if ($Now -gt $until) {
|
||||
Remove-Item -LiteralPath $path -Force -ErrorAction SilentlyContinue
|
||||
return $false
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
||||
function Test-IdaMcpKeepaliveDeadlockFromFacts {
|
||||
param(
|
||||
[bool]$GuiOwnsPort = $false,
|
||||
[bool]$OpeningInFlight = $false,
|
||||
$LastHealthy = $null,
|
||||
[datetime]$Now = (Get-Date),
|
||||
[int]$MaxUnhealthySeconds = 180
|
||||
)
|
||||
if ($GuiOwnsPort) { return $false }
|
||||
if ($OpeningInFlight) { return $false }
|
||||
if ($null -eq $LastHealthy) { return $false }
|
||||
return ($Now - [datetime]$LastHealthy).TotalSeconds -ge $MaxUnhealthySeconds
|
||||
}
|
||||
|
||||
@@ -230,6 +230,8 @@ $bodyObj = @{
|
||||
}
|
||||
$body = $bodyObj | ConvertTo-Json -Depth 12 -Compress
|
||||
|
||||
Set-IdaMcpOpeningLock -TtlSeconds ($TimeoutSeconds + 60)
|
||||
|
||||
$openJob = Start-Job -ScriptBlock {
|
||||
param($RequestBody, $RequestPort)
|
||||
try {
|
||||
@@ -368,6 +370,7 @@ try {
|
||||
Write-Output "ERR:$err"
|
||||
exit 1
|
||||
} finally {
|
||||
Clear-IdaMcpOpeningLock
|
||||
if ($openJob) {
|
||||
Stop-Job -Job $openJob -ErrorAction SilentlyContinue
|
||||
Remove-Job -Job $openJob -Force -ErrorAction SilentlyContinue
|
||||
|
||||
@@ -23,6 +23,8 @@ param(
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
. (Join-Path $PSScriptRoot 'IdaOpenHelpers.ps1')
|
||||
|
||||
function Get-IdaMcpLogDir {
|
||||
$dir = Join-Path $env:LOCALAPPDATA 'reverse-skill\ida-mcp'
|
||||
if (-not (Test-Path -LiteralPath $dir)) {
|
||||
@@ -347,27 +349,22 @@ if ($guiOwners.Count -gt 0) {
|
||||
|
||||
if (-not $Force) {
|
||||
if ($probe.Status -eq 'healthy') {
|
||||
Write-IdaMcpLastHealthy
|
||||
Write-Output "OK:$($probe.Count)`:reuse"
|
||||
exit 0
|
||||
}
|
||||
if ($probe.Status -eq 'busy') {
|
||||
$deadlock = $false
|
||||
$now = Get-Date
|
||||
foreach ($ownerPid in @($probe.Owners)) {
|
||||
if (Test-IdaGuiProcess -ProcessId $ownerPid) { continue }
|
||||
if (-not (Test-ManagedSupervisorProcess -ProcessId $ownerPid)) { continue }
|
||||
$proc = Get-IdaMcpProcessInfo -ProcessId $ownerPid
|
||||
if ($proc -and $proc.CreationDate -and (($now - $proc.CreationDate).TotalSeconds -ge 180)) {
|
||||
$deadlock = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
$deadlock = Test-IdaMcpKeepaliveDeadlockFromFacts `
|
||||
-GuiOwnsPort $false `
|
||||
-OpeningInFlight (Test-IdaMcpOpeningInFlight) `
|
||||
-LastHealthy (Read-IdaMcpLastHealthy) `
|
||||
-Now (Get-Date)
|
||||
if (-not $deadlock) {
|
||||
Write-Output ("WARN:busy:port={0} pid={1}" -f $Port, ($probe.Owners -join ','))
|
||||
Write-Output 'HINT: 13337 is listening but tools/list timed out (likely idb_open). Not killing supervisor.'
|
||||
exit 0
|
||||
}
|
||||
Write-Output ("INFO:deadlock:port={0} pid={1} (tools/list dead >180s, replacing)" -f $Port, ($probe.Owners -join ','))
|
||||
Write-Output ("INFO:deadlock:port={0} pid={1} (tools/list unhealthy >180s, replacing)" -f $Port, ($probe.Owners -join ','))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,6 +505,7 @@ for ($i = 0; $i -lt $WaitSeconds; $i++) {
|
||||
Start-Sleep -Seconds 1
|
||||
$toolCount = Test-IdaMcpHealth -Port $Port
|
||||
if ($toolCount -gt 0) {
|
||||
Write-IdaMcpLastHealthy
|
||||
Write-Output "OK:$toolCount"
|
||||
$ready = $true
|
||||
break
|
||||
|
||||
@@ -4,8 +4,8 @@ Ensure IDA Pro MCP HTTP is healthy; start or replace it when needed.
|
||||
|
||||
.DESCRIPTION
|
||||
One-shot health check used by the scheduled task. Safe to run every minute:
|
||||
a live server is reused; GUI / fresh idb_open busy is reused; a managed
|
||||
supervisor older than 3 minutes that cannot answer tools/list is replaced
|
||||
a live server is reused; GUI / open.ps1 in-flight / last-healthy younger
|
||||
than 3 minutes is reused; tools/list unhealthy for 3 minutes is replaced
|
||||
via start.ps1 -Force; a dead listener is started via start.ps1.
|
||||
|
||||
Usage:
|
||||
@@ -18,6 +18,8 @@ param(
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
. (Join-Path $PSScriptRoot 'IdaOpenHelpers.ps1')
|
||||
|
||||
$logDir = Join-Path $env:LOCALAPPDATA 'reverse-skill\ida-mcp'
|
||||
if (-not (Test-Path -LiteralPath $logDir)) {
|
||||
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
||||
@@ -66,9 +68,8 @@ function Probe-IdaMcp {
|
||||
return @{ Status = 'stale'; Count = $count }
|
||||
}
|
||||
} catch {}
|
||||
# Listen + RPC timeout: GUI or a fresh supervisor during idb_open = busy.
|
||||
# A managed supervisor older than 3 minutes that cannot answer tools/list
|
||||
# is a deadlock (Streamable HTTP GET /mcp holding single-thread HTTPServer).
|
||||
# Listen + RPC timeout: GUI or in-flight idb_open = busy.
|
||||
# Deadlock is consecutive tools/list failures >180s (last-healthy), not process age.
|
||||
if ($owners.Count -gt 0) {
|
||||
return @{ Status = 'busy'; Count = 0; Owners = $owners }
|
||||
}
|
||||
@@ -87,37 +88,20 @@ function Test-IdaGuiProcess {
|
||||
return [string]$proc.Name -match '(?i)^(ida|ida64|idaq|idaq64)\.exe$'
|
||||
}
|
||||
|
||||
function Test-ManagedSupervisorProcess {
|
||||
param([int]$ProcessId)
|
||||
$proc = Get-IdaMcpProcessInfo -ProcessId $ProcessId
|
||||
if (-not $proc) { return $false }
|
||||
$name = [string]$proc.Name
|
||||
$cmd = [string]$proc.CommandLine
|
||||
if ($name -match '(?i)^(ida|ida64|idaq|idaq64)\.exe$') { return $false }
|
||||
if ($name -match '(?i)^(python|pythonw|cmd)\.exe$') {
|
||||
return $cmd -match '(?i)(run-supervisor\.py|idalib_supervisor|idalib-mcp|ida-pro-mcp)'
|
||||
}
|
||||
return $name -match '(?i)^(idalib-mcp|ida-pro-mcp|idalib_supervisor)'
|
||||
}
|
||||
|
||||
function Test-DeadlockedSupervisor {
|
||||
param([int[]]$Owners, [int]$MaxAgeSeconds = 180)
|
||||
param([int[]]$Owners)
|
||||
$gui = @($Owners | Where-Object { Test-IdaGuiProcess -ProcessId $_ })
|
||||
if ($gui.Count -gt 0) { return $false }
|
||||
$now = Get-Date
|
||||
$managed = @($Owners | Where-Object { Test-ManagedSupervisorProcess -ProcessId $_ })
|
||||
if ($managed.Count -eq 0) { return $false }
|
||||
foreach ($pid in $managed) {
|
||||
$proc = Get-IdaMcpProcessInfo -ProcessId $pid
|
||||
if (-not $proc -or -not $proc.CreationDate) { continue }
|
||||
$age = ($now - $proc.CreationDate).TotalSeconds
|
||||
if ($age -ge $MaxAgeSeconds) { return $true }
|
||||
}
|
||||
return $false
|
||||
return Test-IdaMcpKeepaliveDeadlockFromFacts `
|
||||
-GuiOwnsPort $false `
|
||||
-OpeningInFlight (Test-IdaMcpOpeningInFlight) `
|
||||
-LastHealthy (Read-IdaMcpLastHealthy) `
|
||||
-Now (Get-Date)
|
||||
}
|
||||
|
||||
$probe = Probe-IdaMcp -Port $Port
|
||||
if ($probe.Status -eq 'healthy') {
|
||||
Write-IdaMcpLastHealthy
|
||||
Write-WatchLog "OK:$($probe.Count)`:reuse"
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -67,6 +67,23 @@ foreach ($name in @($idaFiles.Keys)) {
|
||||
}
|
||||
}
|
||||
|
||||
$now = Get-Date
|
||||
if (Test-IdaMcpKeepaliveDeadlockFromFacts -GuiOwnsPort $true -OpeningInFlight $false -LastHealthy $now.AddMinutes(-10) -Now $now) {
|
||||
Bad 'GUI owner must not be deadlock'
|
||||
} else { Ok 'GUI owner is not deadlock' }
|
||||
if (Test-IdaMcpKeepaliveDeadlockFromFacts -GuiOwnsPort $false -OpeningInFlight $true -LastHealthy $now.AddMinutes(-10) -Now $now) {
|
||||
Bad 'in-flight open must not be deadlock'
|
||||
} else { Ok 'in-flight open is not deadlock' }
|
||||
if (Test-IdaMcpKeepaliveDeadlockFromFacts -GuiOwnsPort $false -OpeningInFlight $false -LastHealthy $null -Now $now) {
|
||||
Bad 'never-healthy must not Force'
|
||||
} else { Ok 'never-healthy is not deadlock' }
|
||||
if (Test-IdaMcpKeepaliveDeadlockFromFacts -GuiOwnsPort $false -OpeningInFlight $false -LastHealthy $now.AddSeconds(-10) -Now $now) {
|
||||
Bad 'recent last-healthy must not be deadlock'
|
||||
} else { Ok 'recent last-healthy is not deadlock' }
|
||||
if (Test-IdaMcpKeepaliveDeadlockFromFacts -GuiOwnsPort $false -OpeningInFlight $false -LastHealthy $now.AddSeconds(-181) -Now $now) {
|
||||
Ok 'stale last-healthy is deadlock'
|
||||
} else { Bad 'tools/list unhealthy >180s should be deadlock' }
|
||||
|
||||
$recover = Get-Content -LiteralPath $idaFiles['recover.ps1'] -Raw -ErrorAction SilentlyContinue
|
||||
if ($recover -match '(?i)start\.ps1' -and $recover -match '-Force') {
|
||||
Ok 'recover.ps1 calls start.ps1 -Force'
|
||||
@@ -80,10 +97,10 @@ if ($recover -match '(?im)^\s*(&\s*)?taskkill(\.exe)?\s+[^\n]*/T\b') {
|
||||
}
|
||||
|
||||
$start = Get-Content -LiteralPath $idaFiles['start.ps1'] -Raw
|
||||
if ($start -match 'TotalSeconds\s+-ge\s+180' -and $start -match 'INFO:deadlock') {
|
||||
Ok 'start.ps1 deadlock replace after 180s'
|
||||
if ($start -match 'Test-IdaMcpKeepaliveDeadlockFromFacts' -and $start -match 'Write-IdaMcpLastHealthy' -and $start -notmatch 'CreationDate') {
|
||||
Ok 'start.ps1 deadlock uses last-healthy, not CreationDate'
|
||||
} else {
|
||||
Bad 'start.ps1 missing 180s deadlock replace'
|
||||
Bad 'start.ps1 must use last-healthy deadlock, not process CreationDate'
|
||||
}
|
||||
if ($start -match '(?im)^\s*(&\s*)?taskkill(\.exe)?\s+[^\n]*/T\b') {
|
||||
Bad 'start.ps1 must not taskkill /T'
|
||||
@@ -92,10 +109,22 @@ if ($start -match '(?im)^\s*(&\s*)?taskkill(\.exe)?\s+[^\n]*/T\b') {
|
||||
}
|
||||
|
||||
$watch = Get-Content -LiteralPath $idaFiles['watchdog.ps1'] -Raw
|
||||
if ($watch -match 'Test-DeadlockedSupervisor' -and $watch -match '-Force') {
|
||||
Ok 'watchdog.ps1 Force-replaces deadlocked supervisor'
|
||||
if ($watch -match 'Test-IdaMcpKeepaliveDeadlockFromFacts' -and $watch -match 'Test-IdaMcpOpeningInFlight' -and $watch -match '-Force') {
|
||||
Ok 'watchdog.ps1 Force-replaces only last-healthy deadlock'
|
||||
} else {
|
||||
Bad 'watchdog.ps1 missing deadlock -Force path'
|
||||
Bad 'watchdog.ps1 missing last-healthy deadlock -Force path'
|
||||
}
|
||||
if ($watch -match 'CreationDate') {
|
||||
Bad 'watchdog.ps1 must not use process CreationDate'
|
||||
} else {
|
||||
Ok 'watchdog.ps1 has no CreationDate deadlock'
|
||||
}
|
||||
|
||||
$open = Get-Content -LiteralPath (Join-Path $idaDir 'open.ps1') -Raw
|
||||
if ($open -match 'Set-IdaMcpOpeningLock' -and $open -match 'Clear-IdaMcpOpeningLock') {
|
||||
Ok 'open.ps1 holds opening.lock during idb_open'
|
||||
} else {
|
||||
Bad 'open.ps1 must set and clear opening.lock'
|
||||
}
|
||||
|
||||
$py = Get-Content -LiteralPath $idaFiles['run-supervisor.py'] -Raw
|
||||
|
||||
Reference in New Issue
Block a user