From 86aebc102201192870633de13931a95b3c221401 Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Thu, 14 Jul 2022 19:50:17 +0000 Subject: [PATCH 1/7] mega traces: some early work Signed-off-by: Abena Laast --- src/dune | 2 +- src/trace.ml | 82 +++++++++++++++++++++++++++++++++++++- src/tracing_tool_output.ml | 2 +- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/dune b/src/dune index fbf20bf68..1385ba0d1 100644 --- a/src/dune +++ b/src/dune @@ -15,7 +15,7 @@ (foreign_stubs (language c) (names breakpoint_stubs boot_time_stubs ptrace_stubs)) - (libraries core async core_unix.filename_unix fzf re shell + (libraries core async async_shell core_unix.filename_unix fzf re shell core_unix.sys_unix cohttp cohttp_static_handler core_unix.signal_unix tracing magic_trace magic_trace_core) (inline_tests) diff --git a/src/trace.ml b/src/trace.ml index 278a7c379..1f714ac6b 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -578,6 +578,11 @@ module Make_commands (Backend : Backend_intf.S) = struct and decode_opts = decode_flags and debug_print_perf_commands = debug_print_perf_commands and prog = anon ("COMMAND" %: string) + and _local_view = + flag + "local-view" + no_arg + ~doc:"uses local trace processor binary, for use in large trace files" and argv = flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." in @@ -764,8 +769,83 @@ module Make_commands (Backend : Backend_intf.S) = struct decode_opts) ;; + let auto_command = + (* mostly copied from run_command *) + Command.async_or_error + ~summary:"Does work of run command and then calls trace_processor" + ~readme:(fun () -> + "=== examples ===\n\n\ + # Run a process, snapshotting at ^C or exit\n\ + magic-trace run ./program -- arg1 arg2\n\n\ + # Run and trace all threads of a process, not just the main one, snapshotting \ + at ^C or exit\n\ + magic-trace run -multi-thread ./program -- arg1 arg2\n\n\ + # Run a process, tracing its entire execution (only practical for short-lived \ + processes)\n\ + magic-trace run -full-execution ./program\n") + (let%map_open.Command record_opt_fn = record_flags + and decode_opts = decode_flags + and debug_print_perf_commands = debug_print_perf_commands + and prog = anon ("COMMAND" %: string) + and _local_view = + flag + "local-view" + no_arg + ~doc:"uses local trace processor binary, for use in large trace files" + and argv = + flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." + in + fun () -> + let open Deferred.Or_error.Let_syntax in + let%bind () = check_for_perf () in + let executable = + match Shell.which prog with + | Some path -> path + | None -> failwithf "Can't find executable for %s" prog () + in + let%bind () = + record_opt_fn ~executable ~f:(fun opts -> + let elf = Elf.create opts.executable in + let%bind range_symbols = + evaluate_trace_filter ~trace_filter:opts.trace_filter ~elf + in + let%bind pid = + let argv = prog :: List.concat (Option.to_list argv) in + run_and_record + opts + ~elf + ~debug_print_perf_commands + ~prog + ~argv + ~collection_mode:opts.collection_mode + in + let%bind.Deferred perf_maps = Perf_map.Table.load_by_pids [ pid ] in + decode_to_trace + ~perf_maps + ?range_symbols + ~elf + ~trace_scope:opts.trace_scope + ~debug_print_perf_commands + ~record_dir:opts.record_dir + ~collection_mode:opts.collection_mode + decode_opts) + in + (* let%bind.Deferred () = + Async_shell.run "scp" [ "MAGICTRACE:/home/abena/magic-trace/trace.fxt"; "." ] + in *) + (* let%bind.Deferred () = Async_shell.run "open" [ "http://localhost:9001" ] in + let%bind.Deferred () = + Async_shell.run "~/trace_processor" [ "-D"; "trace.fxt" ] + in *) + return ()) + ;; + let commands = - [ "run", run_command; "attach", attach_command; "decode", decode_command ] + [ "run", run_command + ; "attach", attach_command + ; "decode", decode_command + ; "auto", auto_command + ] ;; end diff --git a/src/tracing_tool_output.ml b/src/tracing_tool_output.ml index 6cf25e74e..33ed320c9 100644 --- a/src/tracing_tool_output.ml +++ b/src/tracing_tool_output.ml @@ -85,7 +85,7 @@ module Serve = struct let handler ~body addr request = let path = request_path request in (* Uncomment this to debug routing *) - (* Core.printf "%s\n%!" path; *) + Core.printf "%s\n%!" path; match path with | "" | "/" | "/index.html" -> respond_index t ~filename (* Serve the trace under any name under /trace/ so only the HTML has to change *) From 1897453fc7d3ec55c879e76d5439748592b250a7 Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Mon, 18 Jul 2022 13:38:21 +0000 Subject: [PATCH 2/7] Add trace_processor_exe and open_url flags to run_command in trace.ml to allow large trace processing and url opening automation Signed-off-by: Abena Laast --- src/trace.ml | 181 +++++++++++++++--------------------- src/tracing_tool_output.ml | 1 + src/tracing_tool_output.mli | 2 + 3 files changed, 80 insertions(+), 104 deletions(-) diff --git a/src/trace.ml b/src/trace.ml index 1f714ac6b..6a1bb7c06 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -561,6 +561,32 @@ module Make_commands (Backend : Backend_intf.S) = struct { Decode_opts.output_config; decode_opts; print_events } ;; + let open_url_flags = + let open Command.Param in + flag + "open-url" + (optional string) + ~doc: + "opens a url to display trace. options are local, magic, or android to open \ + http://localhost:10000, https://magic-trace.org, or https://ui.perfetto.dev \ + respectively" + |> map ~f:(fun user_input -> + Option.map user_input ~f:(fun user_choice -> + match user_choice with + | "local" -> "http://localhost:10000" + | "magic" -> "https://magic-trace.org" + | "android" -> "https://ui.perfetto.dev" + | _ -> raise_s [%message "unkown user input" (user_choice : string)])) + ;; + + let use_processor_flag = + let open Command.Param in + flag + "use-processor-exe" + (optional string) + ~doc:"path for processor exe to use to process trace file" + ;; + let run_command = Command.async_or_error ~summary:"Runs a command and traces it." @@ -573,16 +599,16 @@ module Make_commands (Backend : Backend_intf.S) = struct magic-trace run -multi-thread ./program -- arg1 arg2\n\n\ # Run a process, tracing its entire execution (only practical for short-lived \ processes)\n\ - magic-trace run -full-execution ./program\n") + magic-trace run -full-execution ./program\n\ + # Run a process that generates a large trace file, and view it on \ + magic-trace.org magic-trace run ./program -open-url magic -use-processor-exe \ + ~/local-trace-processor\n") (let%map_open.Command record_opt_fn = record_flags and decode_opts = decode_flags and debug_print_perf_commands = debug_print_perf_commands and prog = anon ("COMMAND" %: string) - and _local_view = - flag - "local-view" - no_arg - ~doc:"uses local trace processor binary, for use in large trace files" + and trace_processor_exe = use_processor_flag + and url = open_url_flags and argv = flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." in @@ -594,31 +620,53 @@ module Make_commands (Backend : Backend_intf.S) = struct | Some path -> path | None -> failwithf "Can't find executable for %s" prog () in - record_opt_fn ~executable ~f:(fun opts -> - let elf = Elf.create opts.executable in - let%bind range_symbols = - evaluate_trace_filter ~trace_filter:opts.trace_filter ~elf - in - let%bind pid = - let argv = prog :: List.concat (Option.to_list argv) in - run_and_record - opts + let%bind () = + record_opt_fn ~executable ~f:(fun opts -> + let elf = Elf.create opts.executable in + let%bind range_symbols = + evaluate_trace_filter ~trace_filter:opts.trace_filter ~elf + in + let%bind pid = + let argv = prog :: List.concat (Option.to_list argv) in + run_and_record + opts + ~elf + ~debug_print_perf_commands + ~prog + ~argv + ~collection_mode:opts.collection_mode + in + let%bind.Deferred perf_maps = Perf_map.Table.load_by_pids [ pid ] in + decode_to_trace + ~perf_maps + ?range_symbols ~elf + ~trace_scope:opts.trace_scope ~debug_print_perf_commands - ~prog - ~argv + ~record_dir:opts.record_dir ~collection_mode:opts.collection_mode - in - let%bind.Deferred perf_maps = Perf_map.Table.load_by_pids [ pid ] in - decode_to_trace - ~perf_maps - ?range_symbols - ~elf - ~trace_scope:opts.trace_scope - ~debug_print_perf_commands - ~record_dir:opts.record_dir - ~collection_mode:opts.collection_mode - decode_opts)) + decode_opts) + in + let%bind.Deferred () = + match url with + | None -> Deferred.return () + | Some url -> Async_shell.run "open" [ url ] + in + let output_config = decode_opts.Decode_opts.output_config in + let output = Tracing_tool_output.output output_config in + let output_file = + match output with + | `Sexp _ -> failwith "unimplemented" + | `Fuchsia store_path -> store_path + in + let%bind.Deferred () = + match trace_processor_exe with + | None -> + print_endline "warning: must use local processor on large trace files"; + Deferred.return () + | Some processor_path -> Async_shell.run processor_path [ "-D"; output_file ] + in + return ()) ;; let select_pid () = @@ -769,83 +817,8 @@ module Make_commands (Backend : Backend_intf.S) = struct decode_opts) ;; - let auto_command = - (* mostly copied from run_command *) - Command.async_or_error - ~summary:"Does work of run command and then calls trace_processor" - ~readme:(fun () -> - "=== examples ===\n\n\ - # Run a process, snapshotting at ^C or exit\n\ - magic-trace run ./program -- arg1 arg2\n\n\ - # Run and trace all threads of a process, not just the main one, snapshotting \ - at ^C or exit\n\ - magic-trace run -multi-thread ./program -- arg1 arg2\n\n\ - # Run a process, tracing its entire execution (only practical for short-lived \ - processes)\n\ - magic-trace run -full-execution ./program\n") - (let%map_open.Command record_opt_fn = record_flags - and decode_opts = decode_flags - and debug_print_perf_commands = debug_print_perf_commands - and prog = anon ("COMMAND" %: string) - and _local_view = - flag - "local-view" - no_arg - ~doc:"uses local trace processor binary, for use in large trace files" - and argv = - flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." - in - fun () -> - let open Deferred.Or_error.Let_syntax in - let%bind () = check_for_perf () in - let executable = - match Shell.which prog with - | Some path -> path - | None -> failwithf "Can't find executable for %s" prog () - in - let%bind () = - record_opt_fn ~executable ~f:(fun opts -> - let elf = Elf.create opts.executable in - let%bind range_symbols = - evaluate_trace_filter ~trace_filter:opts.trace_filter ~elf - in - let%bind pid = - let argv = prog :: List.concat (Option.to_list argv) in - run_and_record - opts - ~elf - ~debug_print_perf_commands - ~prog - ~argv - ~collection_mode:opts.collection_mode - in - let%bind.Deferred perf_maps = Perf_map.Table.load_by_pids [ pid ] in - decode_to_trace - ~perf_maps - ?range_symbols - ~elf - ~trace_scope:opts.trace_scope - ~debug_print_perf_commands - ~record_dir:opts.record_dir - ~collection_mode:opts.collection_mode - decode_opts) - in - (* let%bind.Deferred () = - Async_shell.run "scp" [ "MAGICTRACE:/home/abena/magic-trace/trace.fxt"; "." ] - in *) - (* let%bind.Deferred () = Async_shell.run "open" [ "http://localhost:9001" ] in - let%bind.Deferred () = - Async_shell.run "~/trace_processor" [ "-D"; "trace.fxt" ] - in *) - return ()) - ;; - let commands = - [ "run", run_command - ; "attach", attach_command - ; "decode", decode_command - ; "auto", auto_command - ] + [ "run", run_command; "attach", attach_command; "decode", decode_command ] ;; end diff --git a/src/tracing_tool_output.ml b/src/tracing_tool_output.ml index 33ed320c9..2fd74b047 100644 --- a/src/tracing_tool_output.ml +++ b/src/tracing_tool_output.ml @@ -116,6 +116,7 @@ type t = { serve : Serve.t ; output : [ `Fuchsia of string | `Sexp of string ] } +[@@deriving fields] let store_path = function | `Fuchsia store_path | `Sexp store_path -> store_path diff --git a/src/tracing_tool_output.mli b/src/tracing_tool_output.mli index 75ad56227..df27546b0 100644 --- a/src/tracing_tool_output.mli +++ b/src/tracing_tool_output.mli @@ -3,6 +3,8 @@ open! Async type t +val output : t -> [ `Fuchsia of string | `Sexp of string ] + (** Offers configuration parameters for where to save a file and whether to serve it *) val param : t Command.Param.t From 39fc733e12f84b16c5f98227300f46a7a27fc67e Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Mon, 18 Jul 2022 14:54:48 +0000 Subject: [PATCH 3/7] Update use_processor_flag doc Signed-off-by: Abena Laast --- src/trace.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trace.ml b/src/trace.ml index 6a1bb7c06..4f7a1830e 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -584,7 +584,7 @@ module Make_commands (Backend : Backend_intf.S) = struct flag "use-processor-exe" (optional string) - ~doc:"path for processor exe to use to process trace file" + ~doc:"path for standalone processor exe to use to process trace file" ;; let run_command = From 4a91831f855e0000e7e526f3062cc3ed1c5e1734 Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Tue, 2 Aug 2022 15:28:52 +0000 Subject: [PATCH 4/7] close stdout and stderr, and write to devnull in supports_command, remove open_url flag, add processor_path env var and remove arg for use_processor_shell_path flag, create Enable module for processor_path param Signed-off-by: Abena Laast --- src/env_vars.ml | 7 +++- src/env_vars.mli | 1 + src/trace.ml | 86 +++++++++++++++++++++----------------- src/tracing_tool_output.ml | 2 +- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/env_vars.ml b/src/env_vars.ml index fca4b3d84..19e56ec92 100644 --- a/src/env_vars.ml +++ b/src/env_vars.ml @@ -1,7 +1,7 @@ open! Core open Async -(* Points to a filesystem path will a copy of Perfetto. If provided, magic-trace will +(* Points to a filesystem path with a copy of Perfetto. If provided, magic-trace will automatically start a local HTTP server for you to view the trace. You can use this "hidden" feature to serve a local copy of Perfetto if you don't want to copy trace files around. *) @@ -22,3 +22,8 @@ let debug = Option.is_some (Unix.getenv "MAGIC_TRACE_DEBUG") [--dlfilter], this environment variable allows the user to forcibly disable filtering. *) let no_dlfilter = Option.is_some (Unix.getenv "MAGIC_TRACE_NO_DLFILTER") + +(* Points to a filesystem path with a trace processor executable. + If provided, the flag can be indicated to automatically run the processor + at the path once the trace file is created *) +let processor_path = Unix.getenv "MAGIC_TRACE_PROCESSOR_SHELL_PATH" diff --git a/src/env_vars.mli b/src/env_vars.mli index 9113c8f0c..3ae72a98b 100644 --- a/src/env_vars.mli +++ b/src/env_vars.mli @@ -4,3 +4,4 @@ val debug : bool val perf_is_privileged : bool val perfetto_dir : string option val no_dlfilter : bool +val processor_path : string option diff --git a/src/trace.ml b/src/trace.ml index 4f7a1830e..a5e2a78cc 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -8,8 +8,9 @@ let supports_command command = Lazy.from_fun (fun () -> match Core_unix.fork () with | `In_the_child -> - Core_unix.close Core_unix.stdout; - Core_unix.close Core_unix.stderr; + let devnull = Core_unix.openfile ~mode:[ O_WRONLY ] "/dev/null" in + Core_unix.dup2 ~src:devnull ~dst:Core_unix.stdout (); + Core_unix.dup2 ~src:devnull ~dst:Core_unix.stderr (); Core_unix.exec ~prog:command ~argv:[ command; "--version" ] ~use_path:true () |> never_returns | `In_the_parent pid -> @@ -561,30 +562,39 @@ module Make_commands (Backend : Backend_intf.S) = struct { Decode_opts.output_config; decode_opts; print_events } ;; - let open_url_flags = - let open Command.Param in - flag - "open-url" - (optional string) - ~doc: - "opens a url to display trace. options are local, magic, or android to open \ - http://localhost:10000, https://magic-trace.org, or https://ui.perfetto.dev \ - respectively" - |> map ~f:(fun user_input -> - Option.map user_input ~f:(fun user_choice -> - match user_choice with - | "local" -> "http://localhost:10000" - | "magic" -> "https://magic-trace.org" - | "android" -> "https://ui.perfetto.dev" - | _ -> raise_s [%message "unkown user input" (user_choice : string)])) - ;; + module Enable = struct + type enabled = { value : string } - let use_processor_flag = - let open Command.Param in - flag - "use-processor-exe" - (optional string) - ~doc:"path for standalone processor exe to use to process trace file" + type t = + | Disabled + | Enabled of enabled + + let processor_param = + match Env_vars.processor_path with + | None -> Command.Param.return Disabled + | Some processor_shell_path -> + let%map_open.Command processor = + flag + "use-trace-processor-shell" + no_arg + ~doc:[%string "use the trace processor set in environment variables"] + in + if processor then Enabled { value = processor_shell_path } else Disabled + ;; + end + + (* Same as [Caml.exit] but does not run at_exit handlers *) + external sys_exit : int -> 'a = "caml_sys_exit" + + let call_trace_processor ?env ~prog ~argv () = + let pr_set_pdeathsig = Or_error.ok_exn Linux_ext.pr_set_pdeathsig in + match Core_unix.fork () with + | `In_the_child -> + pr_set_pdeathsig Signal.kill; + never_returns + (try Core_unix.exec ?env ~prog ~argv () with + | _ -> sys_exit 127) + | `In_the_parent _ -> () ;; let run_command = @@ -600,15 +610,13 @@ module Make_commands (Backend : Backend_intf.S) = struct # Run a process, tracing its entire execution (only practical for short-lived \ processes)\n\ magic-trace run -full-execution ./program\n\ - # Run a process that generates a large trace file, and view it on \ - magic-trace.org magic-trace run ./program -open-url magic -use-processor-exe \ - ~/local-trace-processor\n") + # Run a process that generates a large trace file, magic-trace run ./program \ + -use-trace-processor-shell\n") (let%map_open.Command record_opt_fn = record_flags and decode_opts = decode_flags and debug_print_perf_commands = debug_print_perf_commands and prog = anon ("COMMAND" %: string) - and trace_processor_exe = use_processor_flag - and url = open_url_flags + and trace_processor_exe = Enable.processor_param and argv = flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." in @@ -647,24 +655,24 @@ module Make_commands (Backend : Backend_intf.S) = struct ~collection_mode:opts.collection_mode decode_opts) in - let%bind.Deferred () = - match url with - | None -> Deferred.return () - | Some url -> Async_shell.run "open" [ url ] - in let output_config = decode_opts.Decode_opts.output_config in let output = Tracing_tool_output.output output_config in let output_file = match output with | `Sexp _ -> failwith "unimplemented" - | `Fuchsia store_path -> store_path + | `Fuchsia store_path -> store_path (* path for tracing output file *) in let%bind.Deferred () = match trace_processor_exe with - | None -> - print_endline "warning: must use local processor on large trace files"; + | Disabled -> + print_endline "Warning: must use local processor on large trace files"; Deferred.return () - | Some processor_path -> Async_shell.run processor_path [ "-D"; output_file ] + | Enabled processor_path -> + Deferred.return + (call_trace_processor + ~prog:processor_path.value + ~argv:[ "-D"; output_file ] + ()) in return ()) ;; diff --git a/src/tracing_tool_output.ml b/src/tracing_tool_output.ml index 2fd74b047..69fa7997f 100644 --- a/src/tracing_tool_output.ml +++ b/src/tracing_tool_output.ml @@ -85,7 +85,7 @@ module Serve = struct let handler ~body addr request = let path = request_path request in (* Uncomment this to debug routing *) - Core.printf "%s\n%!" path; + (* Core.printf "%s\n%!" path; *) match path with | "" | "/" | "/index.html" -> respond_index t ~filename (* Serve the trace under any name under /trace/ so only the HTML has to change *) From 679ad5d78c79371330af498d9e50667443d6ef3b Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Tue, 2 Aug 2022 15:47:55 +0000 Subject: [PATCH 5/7] add clarifying comment Signed-off-by: Abena Laast --- src/trace.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/trace.ml b/src/trace.ml index a5e2a78cc..6a52aefd2 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -8,6 +8,7 @@ let supports_command command = Lazy.from_fun (fun () -> match Core_unix.fork () with | `In_the_child -> + (* gracefully hide perf outputs *) let devnull = Core_unix.openfile ~mode:[ O_WRONLY ] "/dev/null" in Core_unix.dup2 ~src:devnull ~dst:Core_unix.stdout (); Core_unix.dup2 ~src:devnull ~dst:Core_unix.stderr (); From 681bf5483a61eb8425f511b2ea861d73c2646810 Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Tue, 2 Aug 2022 18:08:17 +0000 Subject: [PATCH 6/7] remove unnecessary async_shell from libraries Signed-off-by: Abena Laast --- src/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dune b/src/dune index 1385ba0d1..fbf20bf68 100644 --- a/src/dune +++ b/src/dune @@ -15,7 +15,7 @@ (foreign_stubs (language c) (names breakpoint_stubs boot_time_stubs ptrace_stubs)) - (libraries core async async_shell core_unix.filename_unix fzf re shell + (libraries core async core_unix.filename_unix fzf re shell core_unix.sys_unix cohttp cohttp_static_handler core_unix.signal_unix tracing magic_trace magic_trace_core) (inline_tests) From f567768ab73e622b78f293bbcca41ba7e9a8eece Mon Sep 17 00:00:00 2001 From: Abena Laast Date: Fri, 5 Aug 2022 17:26:10 +0000 Subject: [PATCH 7/7] Change MAGIC_TRACE_PROCESSOR_SHELL to MAGIC_TRACE_TRACE_PROCESSOR_SHELL, change processor_path to trace_processor_shell_path, add comment about closing stdout and stderr breaking things, better name for Enable module, inline Enabled, better name for value, CR-someday for generalizing call_trace_processor with the perf version, update processor flag doc to clarify conditional existence Signed-off-by: Abena Laast --- src/env_vars.ml | 2 +- src/env_vars.mli | 2 +- src/trace.ml | 25 +++++++++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/env_vars.ml b/src/env_vars.ml index 19e56ec92..4cd56173b 100644 --- a/src/env_vars.ml +++ b/src/env_vars.ml @@ -26,4 +26,4 @@ let no_dlfilter = Option.is_some (Unix.getenv "MAGIC_TRACE_NO_DLFILTER") (* Points to a filesystem path with a trace processor executable. If provided, the flag can be indicated to automatically run the processor at the path once the trace file is created *) -let processor_path = Unix.getenv "MAGIC_TRACE_PROCESSOR_SHELL_PATH" +let trace_processor_shell_path = Unix.getenv "MAGIC_TRACE_TRACE_PROCESSOR_SHELL_PATH" diff --git a/src/env_vars.mli b/src/env_vars.mli index 3ae72a98b..cbeeca39f 100644 --- a/src/env_vars.mli +++ b/src/env_vars.mli @@ -4,4 +4,4 @@ val debug : bool val perf_is_privileged : bool val perfetto_dir : string option val no_dlfilter : bool -val processor_path : string option +val trace_processor_shell_path : string option diff --git a/src/trace.ml b/src/trace.ml index 6a52aefd2..5151d74bc 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -9,6 +9,7 @@ let supports_command command = match Core_unix.fork () with | `In_the_child -> (* gracefully hide perf outputs *) + (* simply closing stdout and stderr irregularly caused this child process to exit with 1 and halted the overall process of things *) let devnull = Core_unix.openfile ~mode:[ O_WRONLY ] "/dev/null" in Core_unix.dup2 ~src:devnull ~dst:Core_unix.stdout (); Core_unix.dup2 ~src:devnull ~dst:Core_unix.stderr (); @@ -563,15 +564,13 @@ module Make_commands (Backend : Backend_intf.S) = struct { Decode_opts.output_config; decode_opts; print_events } ;; - module Enable = struct - type enabled = { value : string } - + module Trace_processor_config = struct type t = | Disabled - | Enabled of enabled + | Enabled of { trace_processor_shell_path : string } - let processor_param = - match Env_vars.processor_path with + let param = + match Env_vars.trace_processor_shell_path with | None -> Command.Param.return Disabled | Some processor_shell_path -> let%map_open.Command processor = @@ -580,10 +579,13 @@ module Make_commands (Backend : Backend_intf.S) = struct no_arg ~doc:[%string "use the trace processor set in environment variables"] in - if processor then Enabled { value = processor_shell_path } else Disabled + if processor + then Enabled { trace_processor_shell_path = processor_shell_path } + else Disabled ;; end + (* CR-someday abena: generalize call_trace_processor with the perf version *) (* Same as [Caml.exit] but does not run at_exit handlers *) external sys_exit : int -> 'a = "caml_sys_exit" @@ -611,13 +613,16 @@ module Make_commands (Backend : Backend_intf.S) = struct # Run a process, tracing its entire execution (only practical for short-lived \ processes)\n\ magic-trace run -full-execution ./program\n\ - # Run a process that generates a large trace file, magic-trace run ./program \ + # Run a process that generates a large trace file, and automatically process \n\ + \ the file locally (flag only exists when the environment variable \ + called \n\ + \ MAGIC_TRACE_TRACE_PROCESSOR_SHELL is set) magic-trace run ./program \ -use-trace-processor-shell\n") (let%map_open.Command record_opt_fn = record_flags and decode_opts = decode_flags and debug_print_perf_commands = debug_print_perf_commands and prog = anon ("COMMAND" %: string) - and trace_processor_exe = Enable.processor_param + and trace_processor_exe = Trace_processor_config.param and argv = flag "--" escape ~doc:"ARGS Arguments for the command. Ignored by magic-trace." in @@ -671,7 +676,7 @@ module Make_commands (Backend : Backend_intf.S) = struct | Enabled processor_path -> Deferred.return (call_trace_processor - ~prog:processor_path.value + ~prog:processor_path.trace_processor_shell_path ~argv:[ "-D"; output_file ] ()) in