{"record":{"id":"f0301809f4bc7965","repo":"stablyai/orca","slug":"benchmark-process-group-anchor-changed-before-sign","errorCode":null,"errorMessage":"Benchmark process group anchor changed before signaling","messagePattern":"Benchmark process group anchor changed before signaling","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/macos-computer-helper-owner-loss-processes.mjs","lineNumber":283,"sourceCode":"      operations.signalProcess(groupState.anchorPid, 'SIGCONT')\n      groupState.anchorPid = null\n    } catch (error) {\n      if (error?.code === 'ESRCH') {\n        groupState.anchorPid = null\n      } else {\n        throw new AggregateError([error], 'Benchmark pending anchor recovery failed')\n      }\n    }\n  }\n  const anchor = members[0]\n  try {\n    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      }","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/macos-computer-helper-owner-loss-processes.mjs#L265-L301","documentation":"Thrown inside signalValidatedProcessGroup right after SIGSTOP'ing the anchor (members[0]). The code re-fetches all process identities and looks up the anchor pid; if sameIdentity (pid + pgid + command) no longer matches the pre-stop snapshot, the anchor was replaced in the stop window and signaling the group by -pgid would hit the wrong process. This is a deliberate TOCTOU guard, not a recoverable fault.","triggerScenarios":"Between operations.signalProcess(anchor.pid, 'SIGSTOP') and the processIdentities(true).find(...) re-check, the anchor exited and the OS recycled its PID for an unrelated process, so the returned identity has a different pgid or command.","commonSituations":"Long-running benchmark harnesses on systems under heavy process churn, containers where PID recycling is aggressive, or when the anchor helper crashed immediately on SIGSTOP and a sibling process grabbed the PID. Also surfaces if processIdentities is stubbed to return inconsistent data.","solutions":["Treat as a trial-invalid signal: abort the trial, run compensateStoppedGroup, and re-spawn the helper from scratch","Reduce the window between snapshot and re-check by capturing anchor identity and stopping in the same critical section","Confirm the helper was healthy before signaling (waitForIdentityExit on a no-op signal 0) to avoid stopping an already-dying process","If recurring, raise the helper's SIGCHLD handling so it does not self-terminate on SIGSTOP"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  signalValidatedProcessGroup(pgid, frag, sig, state)\n} catch (error) {\n  if (/anchor changed before signaling/.test(error.message)) {\n    respawnHelperAndRetry()\n  } else throw error\n}","preventionTips":["Treat anchor-identity drift as a signal to re-spawn, not a transient retry","Keep the window between snapshot and SIGSTOP minimal","Log members[0] identity at capture time to compare on failure"],"tags":["race-condition","process-management","signals","toctou","pid-reuse"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}