diff --git a/src/trace.ml b/src/trace.ml index 575ab234f..4c2304623 100644 --- a/src/trace.ml +++ b/src/trace.ml @@ -454,16 +454,14 @@ module Make_commands (Backend : Backend_intf.S) = struct Ptrace.resume pid; (* Forward ^C to the child, unless it has already exited. *) let exited_ivar = Ivar.create () in - Async_unix.Signal.handle - ~stop:(Ivar.read exited_ivar) - Async_unix.Signal.terminating - ~f:(fun signal -> - try - UnixLabels.kill ~pid:(Pid.to_int pid) ~signal:(Signal_unix.to_system_int signal) - with - | Core_unix.Unix_error (_, (_ : string), (_ : string)) -> - (* We raced, but it's OK because the child still exited. *) - ()); + let stop = Ivar.read exited_ivar in + Async_unix.Signal.handle ~stop Async_unix.Signal.terminating ~f:(fun signal -> + try + UnixLabels.kill ~pid:(Pid.to_int pid) ~signal:(Signal_unix.to_system_int signal) + with + | Core_unix.Unix_error (_, (_ : string), (_ : string)) -> + (* We raced, but it's OK because the child still exited. *) + ()); (* [Monitor.try_with] because [waitpid] raises if perf died before we got here. *) let%bind.Deferred (waitpid_result : (Core_unix.Exit_or_signal.t, exn) result) = Monitor.try_with (fun () -> Async_unix.Unix.waitpid pid) @@ -478,6 +476,12 @@ module Make_commands (Backend : Backend_intf.S) = struct error); (* This is still a little racey, but it's the best we can do without pidfds. *) Ivar.fill exited_ivar (); + (* CR-someday tbrindus: [~stop] doesn't make [Async_unix.Signal.handle] restore signal + handlers to their default state, so the decoding step won't be ^C-able. Restore + SIGINT's handler here. Ideally we'd restore all [terminating] handlers to their + default behavior, but I'm not convinced that doesn't break Async and SIGINT is all + we really need. *) + Deferred.upon stop (fun () -> Core.Signal.Expert.set Signal.int `Default); let%bind () = detach attachment in return pid ;; @@ -497,6 +501,7 @@ module Make_commands (Backend : Backend_intf.S) = struct Async_unix.Signal.handle ~stop [ Signal.int ] ~f:(fun (_ : Signal.t) -> Core.eprintf "[ Got signal, detaching... ]\n%!"; Ivar.fill_if_empty done_ivar ()); + Deferred.upon stop (fun () -> Core.Signal.Expert.set Signal.int `Default); Core.eprintf "[ Attached. Press Ctrl-C to stop recording. ]\n%!"; let%bind () = stop in detach attachment