Commit adc79e54c5f65914c668d6d2e7f0ea6f1b4b7cd4
1 parent
0fb3a95c
fix(lifelog): BlockProcessor 崩溃自隔离,防毒块死循环崩 app
某些块的音频会让 sherpa-onnx 在 native 层 SIGSEGV(实测重处理历史时一个 12.8s 正常音频块触发,原因在 native 不可控),把整个进程(含 UI)带崩——表现为「一打开 录音页就闪退」,且重启后 listPending 又排到同一毒块,死循环崩。 native SIGSEGV 无法 try/catch,改用文件标记防御:处理前写 .attempt;若启动时标记 仍在(= 上次崩在这块、没走到删目录),把该块移到 blocks_quarantine/ 跳过。一块最多 崩一次即被隔离,其余正常处理,app 不再死循环。隔离块留存可后续排查。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Showing
1 changed file
with
16 additions
and
0 deletions
lifelog-recorder/app/src/main/kotlin/com/lemon/lifelog/service/BlockProcessor.kt
| ... | ... | @@ -34,6 +34,22 @@ class BlockProcessor( |
| 34 | 34 | private val clusterer: SpeakerClusterer, |
| 35 | 35 | ) { |
| 36 | 36 | suspend fun process(dir: File) { |
| 37 | + // 崩溃自隔离:处理前写 .attempt 标记;若启动时发现标记还在(= 上次处理它时进程在 | |
| 38 | + // native 层崩了,没走到删目录),说明这是「毒块」——移到 blocks_quarantine/ 跳过, | |
| 39 | + // 避免每次重启都崩在同一块上死循环。native SIGSEGV 无法 try/catch,只能这样防御。 | |
| 40 | + val marker = File(dir, ".attempt") | |
| 41 | + if (marker.exists()) { | |
| 42 | + val q = File(dir.parentFile?.parentFile, "blocks_quarantine").apply { mkdirs() } | |
| 43 | + val dest = File(q, dir.name) | |
| 44 | + Log.w(TAG, "block ${dir.name} crashed last attempt → quarantine") | |
| 45 | + withContext(Dispatchers.IO) { | |
| 46 | + dest.deleteRecursively() | |
| 47 | + if (!dir.renameTo(dest)) { dir.copyRecursively(dest, overwrite = true); dir.deleteRecursively() } | |
| 48 | + } | |
| 49 | + return | |
| 50 | + } | |
| 51 | + withContext(Dispatchers.IO) { runCatching { marker.createNewFile() } } | |
| 52 | + | |
| 37 | 53 | val loaded = withContext(Dispatchers.IO) { BlockBuffer.load(dir) } |
| 38 | 54 | if (loaded == null || loaded.samples.isEmpty()) { |
| 39 | 55 | withContext(Dispatchers.IO) { dir.deleteRecursively() } | ... | ... |