From 2b35085358685d24f1637b0d61637e648f4c48bc Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 25 Sep 2026 22:10:07 +0700 Subject: [PATCH] flan run removes its executable and work directory when it is sent SIGTERM or SIGHUP, and the one-shot commands' empty work directory is gone from TODO.org since the exit handler already removes it --- TODO.org | 5 ----- bin/main.ml | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/TODO.org b/TODO.org index 1fc05579..4d9a7af9 100644 --- a/TODO.org +++ b/TODO.org @@ -1795,11 +1795,6 @@ Intermittent, on an unmodified tree too: the =--llvm= half-write daemon in =request= raises =Wire.Closed= uncaught, so test_dev ends with a fatal, no =FAIL= line and every later row unrun. -** TODO flan build and flan run leave an empty flan- directory -=Build.workdir= is created per process and nothing removes it once the IR is -gone. The dev daemon now removes its own on a clean end; the one-shot commands do -not. - ** WAIT An x86 dev session's read of a dyn global after an allocating thunk failed once WAIT on a recurrence; the test now prints the failing read's own reply. The one failure's message came from a second read, which said "kept"; the failing diff --git a/bin/main.ml b/bin/main.ml index baa14c73..78ad8cef 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -949,12 +949,38 @@ let () = ~csrcs:f.csrcs ~lflags:f.lflags ~pnames:(if debug then param_names f.load else []) f.program ~out:exe); - let code = - Sys.command - (String.concat " " (List.map Filename.quote (exe :: prog_args))) + (* Spawned and waited on here rather than through [Sys.command], so a + SIGTERM or SIGHUP sent to flan reaches the program and flan still + removes the executable and its work directory: the default action + would end flan inside the wait with neither removed. SIGINT and + SIGQUIT are ignored while the program runs, as [system] does, since + the terminal sends them to the program too. *) + let pid = + Unix.create_process exe (Array.of_list (exe :: prog_args)) + Unix.stdin Unix.stdout Unix.stderr in + let caught = ref None in + let forward s = + Sys.Signal_handle (fun _ -> + caught := Some s; + try Unix.kill pid s with Unix.Unix_error _ -> ()) + in + Sys.set_signal Sys.sigterm (forward Sys.sigterm); + Sys.set_signal Sys.sighup (forward Sys.sighup); + Sys.set_signal Sys.sigint Sys.Signal_ignore; + Sys.set_signal Sys.sigquit Sys.Signal_ignore; + let rec wait () = + match Unix.waitpid [] pid with + | _, Unix.WEXITED c -> c + | _, (Unix.WSIGNALED _ | Unix.WSTOPPED _) -> 255 + | exception Unix.Unix_error (Unix.EINTR, _, _) -> wait () + in + let code = wait () in (try Sys.remove exe with Sys_error _ -> ()); - exit code) + exit (match !caught with + | Some s when s = Sys.sigterm -> 143 + | Some _ -> 129 + | None -> code)) | _ -> prerr_endline "usage: flan (read|parse|check|emit|shim) ...\n flan check ... [--warn-memory]\n flan emit [--x86] [--dev] [--debug] [--no-bounds-checks]\n\