diff --git a/CHANGES.md b/CHANGES.md index 82ed695b152..170e831f1d6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,8 @@ unreleased - skip directories when looking up programs in the PATH (#1628, fixes #1616, @diml) +- Use `lsof` on macOS to implement `--stats` (#1636, fixes #1634, @xclerc) + - Generate `dune-package` files for every package. These files are installed and read instead of `META` files whenever they are available (#1329, @rgrinberg) diff --git a/src/stats.ml b/src/stats.ml index 191f7732ea2..4cf9912c0a4 100644 --- a/src/stats.ml +++ b/src/stats.ml @@ -5,9 +5,30 @@ let enabled = ref false module Fd_count = struct type t = Unknown | This of int + let try_to_use_lsof () = + (* note: we do not use the Process module here, because it would + create a circular dependency *) + let temp = Filename.temp_file "dune" ".lsof" in + let stdout = + Unix.openfile temp [O_WRONLY; O_CREAT; O_TRUNC; O_SHARE_DELETE] 0o666 + in + let prog = "/usr/sbin/lsof" in + let argv = [prog; "-w"; "-p"; string_of_int (Unix.getpid ())] in + let pid = Spawn.spawn ~prog ~argv ~stdout () in + Unix.close stdout; + match Unix.waitpid [] pid with + | _, Unix.WEXITED 0 -> + let num_lines = List.length (Io.input_lines (open_in temp)) in + This (num_lines - 1) (* the output contains a header line *) + | _ -> Unknown + let get () = match Sys.readdir "/proc/self/fd" with - | exception _ -> Unknown + | exception _ -> + begin match try_to_use_lsof () with + | exception _ -> Unknown + | value -> value + end | files -> This (Array.length files - 1 (* -1 for the dirfd *)) let map2 ~f a b =