MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / cbm_run_posix

Function cbm_run_posix

src/foundation/subprocess.c:314–393  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

312#else /* POSIX */
313
314static int cbm_run_posix(const cbm_proc_opts_t *opts, cbm_proc_result_t *out) {
315 pid_t pid = fork();
316 if (pid < 0) {
317 out->outcome = CBM_PROC_SPAWN_FAILED;
318 out->exit_code = -1;
319 out->term_signal = 0;
320 return -1;
321 }
322 if (pid == 0) {
323 /* Child: redirect stdout+stderr to the log (or discard), then exec.
324 * Use open()+dup2() (async-signal-safe, no malloc) rather than freopen():
325 * the parent may be multithreaded (the MCP server holds worker/watcher/http
326 * threads plus mimalloc/sqlite global state), and a fork() copies
327 * only the calling thread — a malloc between fork and exec could deadlock on
328 * a lock another thread held at fork time. open/dup2/execv touch no heap. */
329 const char *bin = opts->bin;
330 const char *const default_argv[] = {bin, NULL};
331 const char *const *argv = opts->argv ? opts->argv : default_argv;
332 const char *target = opts->log_file ? opts->log_file : "/dev/null";
333 int fd = open(target, O_WRONLY | O_CREAT | O_TRUNC, 0644);
334 if (fd >= 0) {
335 (void)dup2(fd, STDOUT_FILENO);
336 (void)dup2(fd, STDERR_FILENO);
337 if (fd > STDERR_FILENO) {
338 (void)close(fd);
339 }
340 }
341 execv(bin, (char *const *)argv);
342 _exit(127); /* exec failed */
343 }
344
345 long tail_pos = 0;
346 uint64_t last_activity = cbm_now_ms();
347 bool timed_out = false;
348 int wstatus = 0;
349 for (;;) {
350 pid_t wr;
351 do {
352 wr = waitpid(pid, &wstatus, WNOHANG);
353 } while (wr < 0 && errno == EINTR);
354 bool done = (wr == pid);
355
356 if (cbm_tail_log(opts->log_file, &tail_pos, opts->on_log_line, opts->log_ud)) {
357 last_activity = cbm_now_ms();
358 }
359 if (done) {
360 break;
361 }
362 if (opts->quiet_timeout_ms > 0 &&
363 (cbm_now_ms() - last_activity) >= (uint64_t)opts->quiet_timeout_ms) {
364 kill(pid, SIGKILL);
365 do {
366 wr = waitpid(pid, &wstatus, 0);
367 } while (wr < 0 && errno == EINTR);
368 timed_out = true;
369 break;
370 }
371 struct timespec ts = {0, 100000000L}; /* 100 ms poll */

Callers 1

cbm_subprocess_runFunction · 0.85

Calls 4

cbm_now_msFunction · 0.85
cbm_tail_logFunction · 0.85
cbm_nanosleepFunction · 0.85
cbm_proc_classifyFunction · 0.85

Tested by

no test coverage detected