From 90dd81b090ceaa53ebacaee283ef01aa8e23c2f8 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Fri, 29 Aug 2025 13:10:15 +0200 Subject: [PATCH] Irmin: Correctly reap uname child process in gc_stats * What This commit fixes a potential resource leak in the GC statistics module by ensuring that the child process spawned to execute the `uname` command is properly waited for. This prevents the creation of zombie processes. * Why The previous implementation used `Unix.open_process_in` to determine the operating system but never called the corresponding `Unix.close_process_in`. Failing to close the process channel means the parent process does not wait for the child's termination, leaving the child in a "zombie" state. A proliferation of such zombie processes could potentially exhaust system resources, such as entries in the process table. * How The code has been refactored to explicitly call `Unix.close_process_in` after reading the output from the `uname` command. This call blocks until the child process has terminated and its status has been collected, effectively reaping the process. The call is placed to ensure it executes even if reading from the process's standard output fails. --- brassaia-eio/lib_brassaia_pack/io/io.ml | 15 ++++++++++++--- brassaia/lib_brassaia_pack/unix/gc_stats.ml | 15 ++++++++++++--- irmin/lib_irmin_pack/unix/gc_stats.ml | 15 ++++++++++++--- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/brassaia-eio/lib_brassaia_pack/io/io.ml b/brassaia-eio/lib_brassaia_pack/io/io.ml index b868d9dad7a4..1b95fa53a513 100644 --- a/brassaia-eio/lib_brassaia_pack/io/io.ml +++ b/brassaia-eio/lib_brassaia_pack/io/io.ml @@ -309,9 +309,18 @@ module Unix = struct let is_darwin = lazy (try - match Unix.open_process_in "uname" |> input_line with - | "Darwin" -> true - | _ -> false + let inc = Unix.open_process_in "uname" in + let res = + match input_line inc with + | "Darwin" -> true + | _ -> false + | exception End_of_file -> + (* Something went wrong but we still need to wait for the child + process *) + false + in + ignore (Unix.close_process_in inc) ; + res with Unix.Unix_error _ -> false) let get_wtime () = diff --git a/brassaia/lib_brassaia_pack/unix/gc_stats.ml b/brassaia/lib_brassaia_pack/unix/gc_stats.ml index b056ba5de554..b7c6729dca46 100644 --- a/brassaia/lib_brassaia_pack/unix/gc_stats.ml +++ b/brassaia/lib_brassaia_pack/unix/gc_stats.ml @@ -113,9 +113,18 @@ module Worker = struct let is_darwin = lazy (try - match Unix.open_process_in "uname" |> input_line with - | "Darwin" -> true - | _ -> false + let inc = Unix.open_process_in "uname" in + let res = + match input_line inc with + | "Darwin" -> true + | _ -> false + | exception End_of_file -> + (* Something went wrong but we still need to wait for the child + process *) + false + in + ignore (Unix.close_process_in inc); + res with Unix.Unix_error _ -> false) let get_wtime () = diff --git a/irmin/lib_irmin_pack/unix/gc_stats.ml b/irmin/lib_irmin_pack/unix/gc_stats.ml index f2bbbd81c907..4e778587a52c 100644 --- a/irmin/lib_irmin_pack/unix/gc_stats.ml +++ b/irmin/lib_irmin_pack/unix/gc_stats.ml @@ -113,9 +113,18 @@ module Worker = struct let is_darwin = lazy (try - match Unix.open_process_in "uname" |> input_line with - | "Darwin" -> true - | _ -> false + let inc = Unix.open_process_in "uname" in + let res = + match input_line inc with + | "Darwin" -> true + | _ -> false + | exception End_of_file -> + (* Something went wrong but we still need to wait for the child + process *) + false + in + ignore (Unix.close_process_in inc); + res with Unix.Unix_error _ -> false) let get_wtime () = -- GitLab