{"record":{"id":"a93f7588160d2d4b","repo":"stablyai/orca","slug":"benchmark-process-group-changed-before-signaling","errorCode":null,"errorMessage":"Benchmark process group changed before signaling","messagePattern":"Benchmark process group changed before signaling","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/macos-computer-helper-owner-loss-processes.mjs","lineNumber":295,"sourceCode":"    operations.signalProcess(anchor.pid, 'SIGSTOP')\n    groupState.anchorPid = anchor.pid\n    const stoppedAnchor = operations\n      .processIdentities(true)\n      .find((identity) => identity.pid === anchor.pid)\n    if (!sameIdentity(stoppedAnchor, anchor)) {\n      throw new Error('Benchmark process group anchor changed before signaling')\n    }\n    operations.signalProcess(-pgid, 'SIGSTOP')\n    groupState.stopped = true\n    groupState.anchorPid = null\n    const stoppedMembers = operations\n      .processIdentities(true)\n      .filter((identity) => identity.pgid === pgid)\n    if (\n      stoppedMembers.length === 0 ||\n      stoppedMembers.some((identity) => !identity.command.includes(environmentFragment))\n    ) {\n      throw new Error('Benchmark process group changed before signaling')\n    }\n    if (signal !== 'SIGSTOP') {\n      operations.signalProcess(-pgid, signal)\n      if (signal !== 'SIGKILL') {\n        operations.signalProcess(-pgid, 'SIGCONT')\n      }\n      groupState.stopped = false\n      groupState.anchorPid = null\n    }\n    return true\n  } catch (error) {\n    const recoveryErrors = compensateStoppedGroup(pgid, groupState, operations)\n    if (recoveryErrors.length > 0) {\n      throw new AggregateError(\n        [error, ...recoveryErrors],\n        'Benchmark process group signal recovery failed'\n      )\n    }","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/macos-computer-helper-owner-loss-processes.mjs#L277-L313","documentation":"Thrown after SIGSTOP'ing the whole process group (-pgid). The code re-enumerates members of pgid and requires (a) at least one member survives and (b) every surviving member's command still contains environmentFragment. Failure means the group's composition drifted during the stop — members exited or were replaced by unrelated processes sharing the pgid.","triggerScenarios":"operations.signalProcess(-pgid, 'SIGSTOP') succeeds, but the subsequent processIdentities(true).filter(pgid === ...) returns either an empty list or members whose command no longer contains environmentFragment.","commonSituations":"A helper child exits between the anchor stop and the group stop; a setpgid race places an unrelated process into the same pgid; or environmentFragment was chosen too narrowly and no longer matches the helper's actual command line (e.g. after an argv refactor).","solutions":["Re-run the trial after re-spawning the helper — group drift is not recoverable mid-signal","Widen environmentFragment to a stable argv token that survives helper refactors (an env var like ORCA_BENCH_ROLE rather than a path)","Spawn the helper with setsid or a dedicated posix_spawnattr pgid to prevent foreign processes joining the group","Log stoppedMembers at the catch site to see whether members vanished or commands drifted"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  signalValidatedProcessGroup(pgid, frag, sig, state)\n} catch (error) {\n  if (/process group changed before signaling/.test(error.message)) {\n    respawnHelperAndRetry()\n  } else throw error\n}","preventionTips":["Use a stable environmentFragment (an env var token) rather than a brittle path substring","Spawn helpers with setsid or a dedicated pgid so foreign processes cannot join the group","Log stoppedMembers in the catch to distinguish vanished members from command drift"],"tags":["race-condition","process-management","signals","process-group"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}