diff options
| -rw-r--r-- | tools/perf/builtin-record.c | 127 |
1 files changed, 60 insertions, 67 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8ce62ef7f6c3..2e0d484068d2 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -147,29 +147,19 @@ static void sig_handler(int sig) | |||
| 147 | { | 147 | { |
| 148 | if (sig == SIGCHLD) | 148 | if (sig == SIGCHLD) |
| 149 | child_finished = 1; | 149 | child_finished = 1; |
| 150 | else | ||
| 151 | signr = sig; | ||
| 150 | 152 | ||
| 151 | done = 1; | 153 | done = 1; |
| 152 | signr = sig; | ||
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | static void record__sig_exit(int exit_status __maybe_unused, void *arg) | 156 | static void record__sig_exit(void) |
| 156 | { | 157 | { |
| 157 | struct record *rec = arg; | 158 | if (signr == -1) |
| 158 | int status; | ||
| 159 | |||
| 160 | if (rec->evlist->workload.pid > 0) { | ||
| 161 | if (!child_finished) | ||
| 162 | kill(rec->evlist->workload.pid, SIGTERM); | ||
| 163 | |||
| 164 | wait(&status); | ||
| 165 | if (WIFSIGNALED(status)) | ||
| 166 | psignal(WTERMSIG(status), rec->progname); | ||
| 167 | } | ||
| 168 | |||
| 169 | if (signr == -1 || signr == SIGUSR1) | ||
| 170 | return; | 159 | return; |
| 171 | 160 | ||
| 172 | signal(signr, SIG_DFL); | 161 | signal(signr, SIG_DFL); |
| 162 | raise(signr); | ||
| 173 | } | 163 | } |
| 174 | 164 | ||
| 175 | static int record__open(struct record *rec) | 165 | static int record__open(struct record *rec) |
| @@ -243,27 +233,6 @@ static int process_buildids(struct record *rec) | |||
| 243 | size, &build_id__mark_dso_hit_ops); | 233 | size, &build_id__mark_dso_hit_ops); |
| 244 | } | 234 | } |
| 245 | 235 | ||
| 246 | static void record__exit(int status, void *arg) | ||
| 247 | { | ||
| 248 | struct record *rec = arg; | ||
| 249 | struct perf_data_file *file = &rec->file; | ||
| 250 | |||
| 251 | if (status != 0) | ||
| 252 | return; | ||
| 253 | |||
| 254 | if (!file->is_pipe) { | ||
| 255 | rec->session->header.data_size += rec->bytes_written; | ||
| 256 | |||
| 257 | if (!rec->no_buildid) | ||
| 258 | process_buildids(rec); | ||
| 259 | perf_session__write_header(rec->session, rec->evlist, | ||
| 260 | file->fd, true); | ||
| 261 | perf_session__delete(rec->session); | ||
| 262 | perf_evlist__delete(rec->evlist); | ||
| 263 | symbol__exit(); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | static void perf_event__synthesize_guest_os(struct machine *machine, void *data) | 236 | static void perf_event__synthesize_guest_os(struct machine *machine, void *data) |
| 268 | { | 237 | { |
| 269 | int err; | 238 | int err; |
| @@ -344,18 +313,19 @@ static volatile int workload_exec_errno; | |||
| 344 | * if the fork fails, since we asked by setting its | 313 | * if the fork fails, since we asked by setting its |
| 345 | * want_signal to true. | 314 | * want_signal to true. |
| 346 | */ | 315 | */ |
| 347 | static void workload_exec_failed_signal(int signo, siginfo_t *info, | 316 | static void workload_exec_failed_signal(int signo __maybe_unused, |
| 317 | siginfo_t *info, | ||
| 348 | void *ucontext __maybe_unused) | 318 | void *ucontext __maybe_unused) |
| 349 | { | 319 | { |
| 350 | workload_exec_errno = info->si_value.sival_int; | 320 | workload_exec_errno = info->si_value.sival_int; |
| 351 | done = 1; | 321 | done = 1; |
| 352 | signr = signo; | ||
| 353 | child_finished = 1; | 322 | child_finished = 1; |
| 354 | } | 323 | } |
| 355 | 324 | ||
| 356 | static int __cmd_record(struct record *rec, int argc, const char **argv) | 325 | static int __cmd_record(struct record *rec, int argc, const char **argv) |
| 357 | { | 326 | { |
| 358 | int err; | 327 | int err; |
| 328 | int status = 0; | ||
| 359 | unsigned long waking = 0; | 329 | unsigned long waking = 0; |
| 360 | const bool forks = argc > 0; | 330 | const bool forks = argc > 0; |
| 361 | struct machine *machine; | 331 | struct machine *machine; |
| @@ -367,7 +337,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 367 | 337 | ||
| 368 | rec->progname = argv[0]; | 338 | rec->progname = argv[0]; |
| 369 | 339 | ||
| 370 | on_exit(record__sig_exit, rec); | 340 | atexit(record__sig_exit); |
| 371 | signal(SIGCHLD, sig_handler); | 341 | signal(SIGCHLD, sig_handler); |
| 372 | signal(SIGINT, sig_handler); | 342 | signal(SIGINT, sig_handler); |
| 373 | signal(SIGTERM, sig_handler); | 343 | signal(SIGTERM, sig_handler); |
| @@ -388,32 +358,28 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 388 | workload_exec_failed_signal); | 358 | workload_exec_failed_signal); |
| 389 | if (err < 0) { | 359 | if (err < 0) { |
| 390 | pr_err("Couldn't run the workload!\n"); | 360 | pr_err("Couldn't run the workload!\n"); |
| 361 | status = err; | ||
| 391 | goto out_delete_session; | 362 | goto out_delete_session; |
| 392 | } | 363 | } |
| 393 | } | 364 | } |
| 394 | 365 | ||
| 395 | if (record__open(rec) != 0) { | 366 | if (record__open(rec) != 0) { |
| 396 | err = -1; | 367 | err = -1; |
| 397 | goto out_delete_session; | 368 | goto out_child; |
| 398 | } | 369 | } |
| 399 | 370 | ||
| 400 | if (!rec->evlist->nr_groups) | 371 | if (!rec->evlist->nr_groups) |
| 401 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); | 372 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); |
| 402 | 373 | ||
| 403 | /* | ||
| 404 | * perf_session__delete(session) will be called at record__exit() | ||
| 405 | */ | ||
| 406 | on_exit(record__exit, rec); | ||
| 407 | |||
| 408 | if (file->is_pipe) { | 374 | if (file->is_pipe) { |
| 409 | err = perf_header__write_pipe(file->fd); | 375 | err = perf_header__write_pipe(file->fd); |
| 410 | if (err < 0) | 376 | if (err < 0) |
| 411 | goto out_delete_session; | 377 | goto out_child; |
| 412 | } else { | 378 | } else { |
| 413 | err = perf_session__write_header(session, rec->evlist, | 379 | err = perf_session__write_header(session, rec->evlist, |
| 414 | file->fd, false); | 380 | file->fd, false); |
| 415 | if (err < 0) | 381 | if (err < 0) |
| 416 | goto out_delete_session; | 382 | goto out_child; |
| 417 | } | 383 | } |
| 418 | 384 | ||
| 419 | if (!rec->no_buildid | 385 | if (!rec->no_buildid |
| @@ -421,7 +387,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 421 | pr_err("Couldn't generate buildids. " | 387 | pr_err("Couldn't generate buildids. " |
| 422 | "Use --no-buildid to profile anyway.\n"); | 388 | "Use --no-buildid to profile anyway.\n"); |
| 423 | err = -1; | 389 | err = -1; |
| 424 | goto out_delete_session; | 390 | goto out_child; |
| 425 | } | 391 | } |
| 426 | 392 | ||
| 427 | machine = &session->machines.host; | 393 | machine = &session->machines.host; |
| @@ -431,7 +397,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 431 | process_synthesized_event); | 397 | process_synthesized_event); |
| 432 | if (err < 0) { | 398 | if (err < 0) { |
| 433 | pr_err("Couldn't synthesize attrs.\n"); | 399 | pr_err("Couldn't synthesize attrs.\n"); |
| 434 | goto out_delete_session; | 400 | goto out_child; |
| 435 | } | 401 | } |
| 436 | 402 | ||
| 437 | if (have_tracepoints(&rec->evlist->entries)) { | 403 | if (have_tracepoints(&rec->evlist->entries)) { |
| @@ -447,7 +413,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 447 | process_synthesized_event); | 413 | process_synthesized_event); |
| 448 | if (err <= 0) { | 414 | if (err <= 0) { |
| 449 | pr_err("Couldn't record tracing data.\n"); | 415 | pr_err("Couldn't record tracing data.\n"); |
| 450 | goto out_delete_session; | 416 | goto out_child; |
| 451 | } | 417 | } |
| 452 | rec->bytes_written += err; | 418 | rec->bytes_written += err; |
| 453 | } | 419 | } |
| @@ -475,7 +441,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 475 | err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, | ||
