@@ -89,9 +89,43 @@ module Recording = struct
89
89
type t = { callgraph_mode : Callgraph_mode .t option } [@@ deriving sexp ]
90
90
end
91
91
92
+ module Snapshot_behavior = struct
93
+ module AtExit = struct
94
+ type t =
95
+ | Sigint
96
+ | Sigusr2
97
+ end
98
+
99
+ module Function_call = struct
100
+ type t =
101
+ | Sigusr2
102
+ | Ctlfd of Perf_ctlfd .t
103
+ end
104
+
105
+ type t =
106
+ | Never
107
+ | At_exit of AtExit .t
108
+ | Function_call of Function_call .t
109
+
110
+ let opt t =
111
+ let snapshot_opt =
112
+ match t with
113
+ | Never -> []
114
+ | At_exit Sigint -> [ " --snapshot=e" ]
115
+ | Function_call (Ctlfd _ | Sigusr2 ) | At_exit Sigusr2 -> [ " --snapshot" ]
116
+ in
117
+ let control_opt, invoke_after_fork =
118
+ match t with
119
+ | Never | At_exit (Sigint | Sigusr2 ) | Function_call Sigusr2 -> [] , Fn. id
120
+ | Function_call (Ctlfd ctlfd ) -> Perf_ctlfd. control_opt ctlfd
121
+ in
122
+ snapshot_opt @ control_opt, invoke_after_fork
123
+ ;;
124
+ end
125
+
92
126
type t =
93
127
{ pid : Pid .t
94
- ; when_to_snapshot : [ `at_exit of [ `sigint | `sigusr2 ] | `function_call | `never ]
128
+ ; snapshot_behavior : Snapshot_behavior .t
95
129
}
96
130
97
131
let perf_selector_of_trace_scope : Trace_scope.t -> string = function
@@ -353,23 +387,23 @@ module Recording = struct
353
387
[]
354
388
| None , Intel_processor_trace _ | None , Stacktrace_sampling _ -> []
355
389
in
356
- let when_to_snapshot =
390
+ let snapshot_behavior : Snapshot_behavior.t =
357
391
if full_execution
358
- then `never
392
+ then Never
359
393
else (
360
394
match when_to_snapshot with
361
395
| Magic_trace_or_the_application_terminates ->
362
- if perf_supports_snapshot_on_exit then `at_exit `sigint else `at_exit `sigusr2
363
- | Application_calls_a_function _ -> `function_call )
396
+ if perf_supports_snapshot_on_exit then At_exit Sigint else At_exit Sigusr2
397
+ | Application_calls_a_function _ ->
398
+ Function_call
399
+ (if Perf_capabilities. (do_intersect capabilities ctlfd)
400
+ then Ctlfd (Perf_ctlfd. create () )
401
+ else Sigusr2 ))
364
402
in
365
- let snapshot_opt =
403
+ let snapshot_opt, invoke_after_fork =
366
404
match collection_mode with
367
- | Stacktrace_sampling _ -> []
368
- | Intel_processor_trace _ ->
369
- (match when_to_snapshot with
370
- | `never -> []
371
- | `at_exit `sigint -> [ " --snapshot=e" ]
372
- | `function_call | `at_exit `sigusr2 -> [ " --snapshot" ])
405
+ | Stacktrace_sampling _ -> [] , Fn. id
406
+ | Intel_processor_trace _ -> Snapshot_behavior. opt snapshot_behavior
373
407
in
374
408
let overwrite_opts =
375
409
match collection_mode, full_execution with
@@ -403,6 +437,7 @@ module Recording = struct
403
437
session, it doesn't also send SIGINT to the perf process, allowing us to send it a
404
438
SIGUSR2 first to get it to capture a snapshot before exiting. *)
405
439
Core_unix. setpgid ~of_: perf_pid ~to_: perf_pid;
440
+ invoke_after_fork () ;
406
441
let % map () = Async.Clock_ns. after (Time_ns.Span. of_ms 500.0 ) in
407
442
(* Check that the process hasn't failed after waiting, because there's no point pausing
408
443
to do recording if we've already failed. *)
@@ -412,35 +447,35 @@ module Recording = struct
412
447
| Some (_ , exit ) -> perf_exit_to_or_error exit
413
448
| _ -> Ok ()
414
449
in
415
- ( { pid = perf_pid; when_to_snapshot }
450
+ ( { pid = perf_pid; snapshot_behavior }
416
451
, { Data. callgraph_mode = selected_callgraph_mode } )
417
452
;;
418
453
419
454
let maybe_take_snapshot t ~source =
420
- let signal =
421
- match t.when_to_snapshot , source with
455
+ let should_take_snapshot =
456
+ match t.snapshot_behavior , source with
422
457
(* [`never] only comes up in [-full-execution] mode. In that mode, perf always gives a
423
458
complete trace; there's no snapshotting. *)
424
- | `never , _ -> None
459
+ | Never , _ -> false
425
460
(* Do not snapshot at the end of a program if the user has set up a trigger symbol. *)
426
- | `function_call , `ctrl_c -> None
461
+ | Function_call _ , `ctrl_c -> false
427
462
(* This shouldn't happen unless there was a bug elsewhere. It would imply that a trigger
428
463
symbol was hit when there is no trigger symbol configured. *)
429
- | `at_exit _ , `function_call -> None
464
+ | At_exit _ , `function_call -> false
430
465
(* Trigger symbol was hit, and we're configured to look for them. *)
431
- | `function_call , `function_call -> Some Signal. usr2
466
+ | Function_call _ , `function_call -> true
432
467
(* Ctrl-C was hit, and we're configured to look for that. *)
433
- | `at_exit signal , `ctrl_c ->
434
- (* The actual signal to use varies depending on whether or not the user's version of perf
435
- supports snapshot-at-exit. *)
436
- Some
437
- (match signal with
438
- | `sigint -> Signal. int
439
- | `sigusr2 -> Signal. usr2)
468
+ | At_exit _ , `ctrl_c -> true
440
469
in
441
- match signal with
442
- | None -> ()
443
- | Some signal -> Signal_unix. send_i signal (`Pid t.pid)
470
+ if should_take_snapshot
471
+ then (
472
+ match t.snapshot_behavior with
473
+ | Never -> failwith " unreachable"
474
+ | At_exit Sigusr2 | Function_call Sigusr2 ->
475
+ Signal_unix. send_i Signal. usr2 (`Pid t.pid)
476
+ | At_exit Sigint -> Signal_unix. send_i Signal. int (`Pid t.pid)
477
+ | Function_call (Ctlfd ctlfd ) ->
478
+ Perf_ctlfd. (dispatch_and_block_for_ack ctlfd Command. snapshot))
444
479
;;
445
480
446
481
let finish_recording t =
0 commit comments