MCPcopy Create free account
hub / github.com/EvoMap/evolver / _maybeRestartDaemon

Function _maybeRestartDaemon

src/adapters/scripts/evolver-session-start.js:205–272  ·  view source on GitHub ↗
(evolverRoot)

Source from the content-addressed store, hash-verified

203// - Execution errors are swallowed: this must never cause session-start to
204// error out or delay the LLM context injection.
205function _maybeRestartDaemon(evolverRoot) {
206 try {
207 var autoRestart = String(process.env.EVOLVER_SESSION_AUTO_RESTART || '1').toLowerCase().trim();
208 if (autoRestart === '0' || autoRestart === 'false') return;
209
210 var lifecyclePath = evolverRoot
211 ? path.join(evolverRoot, 'src', 'ops', 'lifecycle.js')
212 : null;
213 if (!lifecyclePath || !fs.existsSync(lifecyclePath)) return;
214
215 // Check if daemon is running by looking for the PID file / lock file.
216 // Lock resolution + lease staleness live in ./_lockPaths (issue #176) —
217 // the same module index.js uses, so the hook can never drift from the
218 // daemon again. It is fs/os/path-only, keeping index.js out of the
219 // hook's require graph (R12), and ships in hookAdapter.js's copy list
220 // for the deployed `.claude/hooks/` layout (PR #163).
221 var lockFile = lockPaths.getLockFilePath();
222 var daemonRunning = false;
223 try {
224 if (fs.existsSync(lockFile)) {
225 var raw = fs.readFileSync(lockFile, 'utf8').trim();
226 var payload = raw && raw[0] === '{' ? JSON.parse(raw) : { pid: parseInt(raw, 10) };
227 if (payload && payload.pid > 0) {
228 // R1: PID-reuse defense. process.kill(pid, 0) only proves SOME
229 // process owns that PID -- after macOS sleep / OOM, the kernel may
230 // have reused the slain daemon's PID for an unrelated process.
231 try { process.kill(payload.pid, 0); daemonRunning = true; } catch (e) {
232 // EPERM = process exists but owned by a different user; still a live daemon.
233 if (e && e.code === 'EPERM') daemonRunning = true;
234 }
235 // Lease staleness overrides kill(0)=alive: a lease-aware daemon
236 // refreshes the lock mtime on a timer, so an expired lease means
237 // dead/wedged regardless of kill(0). Pre-lease locks are never
238 // judged stale by mtime (lockIsStaleByLease handles both).
239 if (daemonRunning && lockPaths.lockIsStaleByLease(lockFile, payload)) {
240 daemonRunning = false;
241 }
242 }
243 }
244 } catch (_) { /* lock file unreadable or absent: assume not running */ }
245
246 if (daemonRunning && _proxyHealthyIfExpected()) return; // already alive, nothing to do
247
248 // Daemon appears dead. Spawn lifecycle.js start in the background so
249 // this session-start script exits immediately (< 50 ms) and does not
250 // block the LLM from getting context.
251 var { spawn } = require('child_process');
252 var child = spawn(
253 process.execPath,
254 [lifecyclePath, 'start'],
255 {
256 detached: true,
257 stdio: 'ignore',
258 cwd: evolverRoot,
259 env: Object.assign({}, process.env),
260 windowsHide: true,
261 }
262 );

Callers 1

runInjectionFunction · 0.85

Calls 2

_proxyHealthyIfExpectedFunction · 0.85
parseMethod · 0.80

Tested by

no test coverage detected