linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/3] perf tools: Handle EINTR error for readn/writen
@ 2014-04-24 13:27 Namhyung Kim
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
                   ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Namhyung Kim @ 2014-04-24 13:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: Ingo Molnar, Peter Zijlstra, Stephane Eranian, LKML, Namhyung Kim

Those readn/writen functions are to ensure read/write does I/O for
a given size exactly.  But ion() - its implementation - does not
handle in case it returns prematurely due to a signal.  As it's not
an error itself so just retry the operation.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/util.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9f66549562bd..7fff6be07f07 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -166,6 +166,8 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 		ssize_t ret = is_read ? read(fd, buf, left) :
 					write(fd, buf, left);
 
+		if (ret < 0 && errno == EINTR)
+			continue;
 		if (ret <= 0)
 			return ret;
 
-- 
1.7.9.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-24 13:27 [PATCH v3 1/3] perf tools: Handle EINTR error for readn/writen Namhyung Kim
@ 2014-04-24 13:27 ` Namhyung Kim
  2014-04-25 13:17   ` Stephane Eranian
                     ` (3 more replies)
  2014-04-24 13:27 ` [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test Namhyung Kim
  2014-05-01  6:30 ` [tip:perf/core] perf tools: Handle EINTR error for readn/writen tip-bot for Namhyung Kim
  2 siblings, 4 replies; 19+ messages in thread
From: Namhyung Kim @ 2014-04-24 13:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: Ingo Molnar, Peter Zijlstra, Stephane Eranian, LKML, Namhyung Kim

Currently perf record doesn't propagate the exit status of a workload
given by the command line.  But sometimes it'd useful if it's
propagated so that a monitoring script can handle errors
appropriately.

To do that, it got rid of exit handlers and run/call them directly in
the __cmd_record().  I don't see any reason why those are in a form of
exit handlers in the first place.  Also it cleaned up the resouce
management code in record__exit().

With this change, perf record returns the child exit status in case of
normal termination.  (Not sure what should be returned on abnormal
cases though).

Example run of Stephane's case:

  $ perf record true && echo yes || echo no
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.013 MB perf.data (~589 samples) ]
  yes

  $ perf record false && echo yes || echo no
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.013 MB perf.data (~589 samples) ]
  no

And Jiri's case (error in parent):

  $ perf record -m 10G true && echo yes || echo no
  rounding mmap pages size to 17179869184 bytes (4194304 pages)
  failed to mmap with 12 (Cannot allocate memory)
  no

Reported-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-record.c |  121 ++++++++++++++++++-------------------------
 1 file changed, 51 insertions(+), 70 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index eb524f91bffe..b1523d8a6191 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -152,26 +152,6 @@ static void sig_handler(int sig)
 	signr = sig;
 }
 
-static void record__sig_exit(int exit_status __maybe_unused, void *arg)
-{
-	struct record *rec = arg;
-	int status;
-
-	if (rec->evlist->workload.pid > 0) {
-		if (!child_finished)
-			kill(rec->evlist->workload.pid, SIGTERM);
-
-		wait(&status);
-		if (WIFSIGNALED(status))
-			psignal(WTERMSIG(status), rec->progname);
-	}
-
-	if (signr == -1 || signr == SIGUSR1)
-		return;
-
-	signal(signr, SIG_DFL);
-}
-
 static int record__open(struct record *rec)
 {
 	char msg[512];
@@ -243,27 +223,6 @@ static int process_buildids(struct record *rec)
 					      size, &build_id__mark_dso_hit_ops);
 }
 
-static void record__exit(int status, void *arg)
-{
-	struct record *rec = arg;
-	struct perf_data_file *file = &rec->file;
-
-	if (status != 0)
-		return;
-
-	if (!file->is_pipe) {
-		rec->session->header.data_size += rec->bytes_written;
-
-		if (!rec->no_buildid)
-			process_buildids(rec);
-		perf_session__write_header(rec->session, rec->evlist,
-					   file->fd, true);
-		perf_session__delete(rec->session);
-		perf_evlist__delete(rec->evlist);
-		symbol__exit();
-	}
-}
-
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
 	int err;
@@ -356,6 +315,7 @@ static void workload_exec_failed_signal(int signo, siginfo_t *info,
 static int __cmd_record(struct record *rec, int argc, const char **argv)
 {
 	int err;
+	int status = 0;
 	unsigned long waking = 0;
 	const bool forks = argc > 0;
 	struct machine *machine;
@@ -367,7 +327,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	rec->progname = argv[0];
 
-	on_exit(record__sig_exit, rec);
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);
@@ -394,26 +353,21 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	if (record__open(rec) != 0) {
 		err = -1;
-		goto out_delete_session;
+		goto out_child;
 	}
 
 	if (!rec->evlist->nr_groups)
 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
 
-	/*
-	 * perf_session__delete(session) will be called at record__exit()
-	 */
-	on_exit(record__exit, rec);
-
 	if (file->is_pipe) {
 		err = perf_header__write_pipe(file->fd);
 		if (err < 0)
-			goto out_delete_session;
+			goto out_child;
 	} else {
 		err = perf_session__write_header(session, rec->evlist,
 						 file->fd, false);
 		if (err < 0)
-			goto out_delete_session;
+			goto out_child;
 	}
 
 	if (!rec->no_buildid
@@ -421,7 +375,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 		pr_err("Couldn't generate buildids. "
 		       "Use --no-buildid to profile anyway.\n");
 		err = -1;
-		goto out_delete_session;
+		goto out_child;
 	}
 
 	machine = &session->machines.host;
@@ -431,7 +385,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
-			goto out_delete_session;
+			goto out_child;
 		}
 
 		if (have_tracepoints(&rec->evlist->entries)) {
@@ -447,7 +401,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 								  process_synthesized_event);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
-				goto out_delete_session;
+				goto out_child;
 			}
 			rec->bytes_written += err;
 		}
@@ -475,7 +429,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
 					    process_synthesized_event, opts->sample_address);
 	if (err != 0)
-		goto out_delete_session;
+		goto out_child;
 
 	if (rec->realtime_prio) {
 		struct sched_param param;
@@ -484,7 +438,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
 			pr_err("Could not set realtime priority.\n");
 			err = -1;
-			goto out_delete_session;
+			goto out_child;
 		}
 	}
 
@@ -512,13 +466,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 		if (record__mmap_read_all(rec) < 0) {
 			err = -1;
-			goto out_delete_session;
+			goto out_child;
 		}
 
 		if (hits == rec->samples) {
 			if (done)
 				break;
 			err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1);
+			if (err < 0 && errno == EINTR)
+				err = 0;
 			waking++;
 		}
 
@@ -538,28 +494,52 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
 		pr_err("Workload failed: %s\n", emsg);
 		err = -1;
-		goto out_delete_session;
+		goto out_child;
 	}
 
-	if (quiet || signr == SIGUSR1)
-		return 0;
+	if (!quiet) {
+		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
 
-	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
+		/*
+		 * Approximate RIP event size: 24 bytes.
+		 */
+		fprintf(stderr,
+			"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
+			(double)rec->bytes_written / 1024.0 / 1024.0,
+			file->path,
+			rec->bytes_written / 24);
+	}
 
-	/*
-	 * Approximate RIP event size: 24 bytes.
-	 */
-	fprintf(stderr,
-		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
-		(double)rec->bytes_written / 1024.0 / 1024.0,
-		file->path,
-		rec->bytes_written / 24);
+out_child:
+	if (forks) {
+		int exit_status;
 
-	return 0;
+		if (!child_finished)
+			kill(rec->evlist->workload.pid, SIGTERM);
+
+		wait(&exit_status);
+
+		if (err < 0)
+			status = err;
+		else if (WIFEXITED(exit_status))
+			status = WEXITSTATUS(exit_status);
+		else if (WIFSIGNALED(status))
+			psignal(WTERMSIG(status), rec->progname);
+	} else
+		status = err;
+
+	if (!err && !file->is_pipe) {
+		rec->session->header.data_size += rec->bytes_written;
+
+		if (!rec->no_buildid)
+			process_buildids(rec);
+		perf_session__write_header(rec->session, rec->evlist,
+					   file->fd, true);
+	}
 
 out_delete_session:
 	perf_session__delete(session);
-	return err;
+	return status;
 }
 
 #define BRANCH_OPT(n, m) \
@@ -988,6 +968,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	err = __cmd_record(&record, argc, argv);
 out_symbol_exit:
+	perf_evlist__delete(rec->evlist);
 	symbol__exit();
 	return err;
 }
-- 
1.7.9.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test
  2014-04-24 13:27 [PATCH v3 1/3] perf tools: Handle EINTR error for readn/writen Namhyung Kim
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
@ 2014-04-24 13:27 ` Namhyung Kim
  2014-04-25 13:18   ` Stephane Eranian
  2014-05-01  6:30 ` [tip:perf/core] perf tools: Handle EINTR error for readn/writen tip-bot for Namhyung Kim
  2 siblings, 1 reply; 19+ messages in thread
From: Namhyung Kim @ 2014-04-24 13:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: Ingo Molnar, Peter Zijlstra, Stephane Eranian, LKML,
	Namhyung Kim, Bernhard Rosenkraenzer, Irina Tirdea

The on_exit() function was only used in perf record but it's gone in
previous patch.

Cc: Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
Cc: Irina Tirdea <irina.tirdea@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-record.c                     |   31 -----------------------
 tools/perf/config/Makefile                      |    8 ------
 tools/perf/config/feature-checks/Makefile       |    4 ---
 tools/perf/config/feature-checks/test-all.c     |    5 ----
 tools/perf/config/feature-checks/test-on-exit.c |   16 ------------
 5 files changed, 64 deletions(-)
 delete mode 100644 tools/perf/config/feature-checks/test-on-exit.c

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b1523d8a6191..1c127806fcb1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -30,37 +30,6 @@
 #include <sched.h>
 #include <sys/mman.h>
 
-#ifndef HAVE_ON_EXIT_SUPPORT
-#ifndef ATEXIT_MAX
-#define ATEXIT_MAX 32
-#endif
-static int __on_exit_count = 0;
-typedef void (*on_exit_func_t) (int, void *);
-static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
-static void *__on_exit_args[ATEXIT_MAX];
-static int __exitcode = 0;
-static void __handle_on_exit_funcs(void);
-static int on_exit(on_exit_func_t function, void *arg);
-#define exit(x) (exit)(__exitcode = (x))
-
-static int on_exit(on_exit_func_t function, void *arg)
-{
-	if (__on_exit_count == ATEXIT_MAX)
-		return -ENOMEM;
-	else if (__on_exit_count == 0)
-		atexit(__handle_on_exit_funcs);
-	__on_exit_funcs[__on_exit_count] = function;
-	__on_exit_args[__on_exit_count++] = arg;
-	return 0;
-}
-
-static void __handle_on_exit_funcs(void)
-{
-	int i;
-	for (i = 0; i < __on_exit_count; i++)
-		__on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
-}
-#endif
 
 struct record {
 	struct perf_tool	tool;
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index ee21fa95ebcf..7b7003d11983 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -156,7 +156,6 @@ CORE_FEATURE_TESTS =			\
 	libpython-version		\
 	libslang			\
 	libunwind			\
-	on-exit				\
 	stackprotector-all		\
 	timerfd				\
 	libdw-dwarf-unwind
@@ -182,7 +181,6 @@ VF_FEATURE_TESTS =			\
 	libelf-getphdrnum		\
 	libelf-mmap			\
 	libpython-version		\
-	on-exit				\
 	stackprotector-all		\
 	timerfd				\
 	libunwind-debug-frame		\
@@ -541,12 +539,6 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),)
   CFLAGS += -DHAVE_LIBBFD_SUPPORT
 endif
 
-ifndef NO_ON_EXIT
-  ifeq ($(feature-on-exit), 1)
-    CFLAGS += -DHAVE_ON_EXIT_SUPPORT
-  endif
-endif
-
 ifndef NO_BACKTRACE
   ifeq ($(feature-backtrace), 1)
     CFLAGS += -DHAVE_BACKTRACE_SUPPORT
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 2da103c53f89..64c84e5f0514 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -24,7 +24,6 @@ FILES=					\
 	test-libslang.bin		\
 	test-libunwind.bin		\
 	test-libunwind-debug-frame.bin	\
-	test-on-exit.bin		\
 	test-stackprotector-all.bin	\
 	test-timerfd.bin		\
 	test-libdw-dwarf-unwind.bin
@@ -133,9 +132,6 @@ test-liberty-z.bin:
 test-cplus-demangle.bin:
 	$(BUILD) -liberty
 
-test-on-exit.bin:
-	$(BUILD)
-
 test-backtrace.bin:
 	$(BUILD)
 
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index fc37eb3ca17b..fe5c1e5c952f 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -69,10 +69,6 @@
 # include "test-libbfd.c"
 #undef main
 
-#define main main_test_on_exit
-# include "test-on-exit.c"
-#undef main
-
 #define main main_test_backtrace
 # include "test-backtrace.c"
 #undef main
@@ -110,7 +106,6 @@ int main(int argc, char *argv[])
 	main_test_gtk2(argc, argv);
 	main_test_gtk2_infobar(argc, argv);
 	main_test_libbfd();
-	main_test_on_exit();
 	main_test_backtrace();
 	main_test_libnuma();
 	main_test_timerfd();
diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
deleted file mode 100644
index 8e88b16e6ded..000000000000
--- a/tools/perf/config/feature-checks/test-on-exit.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-static void exit_fn(int status, void *__data)
-{
-	printf("exit status: %d, data: %d\n", status, *(int *)__data);
-}
-
-static int data = 123;
-
-int main(void)
-{
-	on_exit(exit_fn, &data);
-
-	return 321;
-}
-- 
1.7.9.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
@ 2014-04-25 13:17   ` Stephane Eranian
  2014-04-29 10:56   ` Jiri Olsa
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 19+ messages in thread
From: Stephane Eranian @ 2014-04-25 13:17 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Ingo Molnar, Peter Zijlstra,
	LKML, Namhyung Kim

On Thu, Apr 24, 2014 at 3:27 PM, Namhyung Kim <namhyung@kernel.org> wrote:
> Currently perf record doesn't propagate the exit status of a workload
> given by the command line.  But sometimes it'd useful if it's
> propagated so that a monitoring script can handle errors
> appropriately.
>
> To do that, it got rid of exit handlers and run/call them directly in
> the __cmd_record().  I don't see any reason why those are in a form of
> exit handlers in the first place.  Also it cleaned up the resouce
> management code in record__exit().
>
> With this change, perf record returns the child exit status in case of
> normal termination.  (Not sure what should be returned on abnormal
> cases though).
>
> Example run of Stephane's case:
>
>   $ perf record true && echo yes || echo no
>   [ perf record: Woken up 1 times to write data ]
>   [ perf record: Captured and wrote 0.013 MB perf.data (~589 samples) ]
>   yes
>
>   $ perf record false && echo yes || echo no
>   [ perf record: Woken up 1 times to write data ]
>   [ perf record: Captured and wrote 0.013 MB perf.data (~589 samples) ]
>   no
>
> And Jiri's case (error in parent):
>
>   $ perf record -m 10G true && echo yes || echo no
>   rounding mmap pages size to 17179869184 bytes (4194304 pages)
>   failed to mmap with 12 (Cannot allocate memory)
>   no
>
Works for me, now. Thanks.
Acked-by: Stephane Eranian <eranian@google.com>
> Reported-by: Stephane Eranian <eranian@google.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/builtin-record.c |  121 ++++++++++++++++++-------------------------
>  1 file changed, 51 insertions(+), 70 deletions(-)
>
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index eb524f91bffe..b1523d8a6191 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -152,26 +152,6 @@ static void sig_handler(int sig)
>         signr = sig;
>  }
>
> -static void record__sig_exit(int exit_status __maybe_unused, void *arg)
> -{
> -       struct record *rec = arg;
> -       int status;
> -
> -       if (rec->evlist->workload.pid > 0) {
> -               if (!child_finished)
> -                       kill(rec->evlist->workload.pid, SIGTERM);
> -
> -               wait(&status);
> -               if (WIFSIGNALED(status))
> -                       psignal(WTERMSIG(status), rec->progname);
> -       }
> -
> -       if (signr == -1 || signr == SIGUSR1)
> -               return;
> -
> -       signal(signr, SIG_DFL);
> -}
> -
>  static int record__open(struct record *rec)
>  {
>         char msg[512];
> @@ -243,27 +223,6 @@ static int process_buildids(struct record *rec)
>                                               size, &build_id__mark_dso_hit_ops);
>  }
>
> -static void record__exit(int status, void *arg)
> -{
> -       struct record *rec = arg;
> -       struct perf_data_file *file = &rec->file;
> -
> -       if (status != 0)
> -               return;
> -
> -       if (!file->is_pipe) {
> -               rec->session->header.data_size += rec->bytes_written;
> -
> -               if (!rec->no_buildid)
> -                       process_buildids(rec);
> -               perf_session__write_header(rec->session, rec->evlist,
> -                                          file->fd, true);
> -               perf_session__delete(rec->session);
> -               perf_evlist__delete(rec->evlist);
> -               symbol__exit();
> -       }
> -}
> -
>  static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
>  {
>         int err;
> @@ -356,6 +315,7 @@ static void workload_exec_failed_signal(int signo, siginfo_t *info,
>  static int __cmd_record(struct record *rec, int argc, const char **argv)
>  {
>         int err;
> +       int status = 0;
>         unsigned long waking = 0;
>         const bool forks = argc > 0;
>         struct machine *machine;
> @@ -367,7 +327,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>
>         rec->progname = argv[0];
>
> -       on_exit(record__sig_exit, rec);
>         signal(SIGCHLD, sig_handler);
>         signal(SIGINT, sig_handler);
>         signal(SIGTERM, sig_handler);
> @@ -394,26 +353,21 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>
>         if (record__open(rec) != 0) {
>                 err = -1;
> -               goto out_delete_session;
> +               goto out_child;
>         }
>
>         if (!rec->evlist->nr_groups)
>                 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
>
> -       /*
> -        * perf_session__delete(session) will be called at record__exit()
> -        */
> -       on_exit(record__exit, rec);
> -
>         if (file->is_pipe) {
>                 err = perf_header__write_pipe(file->fd);
>                 if (err < 0)
> -                       goto out_delete_session;
> +                       goto out_child;
>         } else {
>                 err = perf_session__write_header(session, rec->evlist,
>                                                  file->fd, false);
>                 if (err < 0)
> -                       goto out_delete_session;
> +                       goto out_child;
>         }
>
>         if (!rec->no_buildid
> @@ -421,7 +375,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>                 pr_err("Couldn't generate buildids. "
>                        "Use --no-buildid to profile anyway.\n");
>                 err = -1;
> -               goto out_delete_session;
> +               goto out_child;
>         }
>
>         machine = &session->machines.host;
> @@ -431,7 +385,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>                                                    process_synthesized_event);
>                 if (err < 0) {
>                         pr_err("Couldn't synthesize attrs.\n");
> -                       goto out_delete_session;
> +                       goto out_child;
>                 }
>
>                 if (have_tracepoints(&rec->evlist->entries)) {
> @@ -447,7 +401,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>                                                                   process_synthesized_event);
>                         if (err <= 0) {
>                                 pr_err("Couldn't record tracing data.\n");
> -                               goto out_delete_session;
> +                               goto out_child;
>                         }
>                         rec->bytes_written += err;
>                 }
> @@ -475,7 +429,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>         err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
>                                             process_synthesized_event, opts->sample_address);
>         if (err != 0)
> -               goto out_delete_session;
> +               goto out_child;
>
>         if (rec->realtime_prio) {
>                 struct sched_param param;
> @@ -484,7 +438,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>                 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
>                         pr_err("Could not set realtime priority.\n");
>                         err = -1;
> -                       goto out_delete_session;
> +                       goto out_child;
>                 }
>         }
>
> @@ -512,13 +466,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>
>                 if (record__mmap_read_all(rec) < 0) {
>                         err = -1;
> -                       goto out_delete_session;
> +                       goto out_child;
>                 }
>
>                 if (hits == rec->samples) {
>                         if (done)
>                                 break;
>                         err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1);
> +                       if (err < 0 && errno == EINTR)
> +                               err = 0;
>                         waking++;
>                 }
>
> @@ -538,28 +494,52 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>                 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
>                 pr_err("Workload failed: %s\n", emsg);
>                 err = -1;
> -               goto out_delete_session;
> +               goto out_child;
>         }
>
> -       if (quiet || signr == SIGUSR1)
> -               return 0;
> +       if (!quiet) {
> +               fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
>
> -       fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
> +               /*
> +                * Approximate RIP event size: 24 bytes.
> +                */
> +               fprintf(stderr,
> +                       "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
> +                       (double)rec->bytes_written / 1024.0 / 1024.0,
> +                       file->path,
> +                       rec->bytes_written / 24);
> +       }
>
> -       /*
> -        * Approximate RIP event size: 24 bytes.
> -        */
> -       fprintf(stderr,
> -               "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
> -               (double)rec->bytes_written / 1024.0 / 1024.0,
> -               file->path,
> -               rec->bytes_written / 24);
> +out_child:
> +       if (forks) {
> +               int exit_status;
>
> -       return 0;
> +               if (!child_finished)
> +                       kill(rec->evlist->workload.pid, SIGTERM);
> +
> +               wait(&exit_status);
> +
> +               if (err < 0)
> +                       status = err;
> +               else if (WIFEXITED(exit_status))
> +                       status = WEXITSTATUS(exit_status);
> +               else if (WIFSIGNALED(status))
> +                       psignal(WTERMSIG(status), rec->progname);
> +       } else
> +               status = err;
> +
> +       if (!err && !file->is_pipe) {
> +               rec->session->header.data_size += rec->bytes_written;
> +
> +               if (!rec->no_buildid)
> +                       process_buildids(rec);
> +               perf_session__write_header(rec->session, rec->evlist,
> +                                          file->fd, true);
> +       }
>
>  out_delete_session:
>         perf_session__delete(session);
> -       return err;
> +       return status;
>  }
>
>  #define BRANCH_OPT(n, m) \
> @@ -988,6 +968,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
>
>         err = __cmd_record(&record, argc, argv);
>  out_symbol_exit:
> +       perf_evlist__delete(rec->evlist);
>         symbol__exit();
>         return err;
>  }
> --
> 1.7.9.2
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test
  2014-04-24 13:27 ` [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test Namhyung Kim
@ 2014-04-25 13:18   ` Stephane Eranian
  0 siblings, 0 replies; 19+ messages in thread
From: Stephane Eranian @ 2014-04-25 13:18 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Ingo Molnar, Peter Zijlstra,
	LKML, Namhyung Kim, Bernhard Rosenkraenzer, Irina Tirdea

On Thu, Apr 24, 2014 at 3:27 PM, Namhyung Kim <namhyung@kernel.org> wrote:
> The on_exit() function was only used in perf record but it's gone in
> previous patch.
>
Acked-by: Stephane Eranian <eranian@google.com>

> Cc: Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
> Cc: Irina Tirdea <irina.tirdea@intel.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/builtin-record.c                     |   31 -----------------------
>  tools/perf/config/Makefile                      |    8 ------
>  tools/perf/config/feature-checks/Makefile       |    4 ---
>  tools/perf/config/feature-checks/test-all.c     |    5 ----
>  tools/perf/config/feature-checks/test-on-exit.c |   16 ------------
>  5 files changed, 64 deletions(-)
>  delete mode 100644 tools/perf/config/feature-checks/test-on-exit.c
>
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index b1523d8a6191..1c127806fcb1 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -30,37 +30,6 @@
>  #include <sched.h>
>  #include <sys/mman.h>
>
> -#ifndef HAVE_ON_EXIT_SUPPORT
> -#ifndef ATEXIT_MAX
> -#define ATEXIT_MAX 32
> -#endif
> -static int __on_exit_count = 0;
> -typedef void (*on_exit_func_t) (int, void *);
> -static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
> -static void *__on_exit_args[ATEXIT_MAX];
> -static int __exitcode = 0;
> -static void __handle_on_exit_funcs(void);
> -static int on_exit(on_exit_func_t function, void *arg);
> -#define exit(x) (exit)(__exitcode = (x))
> -
> -static int on_exit(on_exit_func_t function, void *arg)
> -{
> -       if (__on_exit_count == ATEXIT_MAX)
> -               return -ENOMEM;
> -       else if (__on_exit_count == 0)
> -               atexit(__handle_on_exit_funcs);
> -       __on_exit_funcs[__on_exit_count] = function;
> -       __on_exit_args[__on_exit_count++] = arg;
> -       return 0;
> -}
> -
> -static void __handle_on_exit_funcs(void)
> -{
> -       int i;
> -       for (i = 0; i < __on_exit_count; i++)
> -               __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
> -}
> -#endif
>
>  struct record {
>         struct perf_tool        tool;
> diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
> index ee21fa95ebcf..7b7003d11983 100644
> --- a/tools/perf/config/Makefile
> +++ b/tools/perf/config/Makefile
> @@ -156,7 +156,6 @@ CORE_FEATURE_TESTS =                        \
>         libpython-version               \
>         libslang                        \
>         libunwind                       \
> -       on-exit                         \
>         stackprotector-all              \
>         timerfd                         \
>         libdw-dwarf-unwind
> @@ -182,7 +181,6 @@ VF_FEATURE_TESTS =                  \
>         libelf-getphdrnum               \
>         libelf-mmap                     \
>         libpython-version               \
> -       on-exit                         \
>         stackprotector-all              \
>         timerfd                         \
>         libunwind-debug-frame           \
> @@ -541,12 +539,6 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),)
>    CFLAGS += -DHAVE_LIBBFD_SUPPORT
>  endif
>
> -ifndef NO_ON_EXIT
> -  ifeq ($(feature-on-exit), 1)
> -    CFLAGS += -DHAVE_ON_EXIT_SUPPORT
> -  endif
> -endif
> -
>  ifndef NO_BACKTRACE
>    ifeq ($(feature-backtrace), 1)
>      CFLAGS += -DHAVE_BACKTRACE_SUPPORT
> diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
> index 2da103c53f89..64c84e5f0514 100644
> --- a/tools/perf/config/feature-checks/Makefile
> +++ b/tools/perf/config/feature-checks/Makefile
> @@ -24,7 +24,6 @@ FILES=                                        \
>         test-libslang.bin               \
>         test-libunwind.bin              \
>         test-libunwind-debug-frame.bin  \
> -       test-on-exit.bin                \
>         test-stackprotector-all.bin     \
>         test-timerfd.bin                \
>         test-libdw-dwarf-unwind.bin
> @@ -133,9 +132,6 @@ test-liberty-z.bin:
>  test-cplus-demangle.bin:
>         $(BUILD) -liberty
>
> -test-on-exit.bin:
> -       $(BUILD)
> -
>  test-backtrace.bin:
>         $(BUILD)
>
> diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
> index fc37eb3ca17b..fe5c1e5c952f 100644
> --- a/tools/perf/config/feature-checks/test-all.c
> +++ b/tools/perf/config/feature-checks/test-all.c
> @@ -69,10 +69,6 @@
>  # include "test-libbfd.c"
>  #undef main
>
> -#define main main_test_on_exit
> -# include "test-on-exit.c"
> -#undef main
> -
>  #define main main_test_backtrace
>  # include "test-backtrace.c"
>  #undef main
> @@ -110,7 +106,6 @@ int main(int argc, char *argv[])
>         main_test_gtk2(argc, argv);
>         main_test_gtk2_infobar(argc, argv);
>         main_test_libbfd();
> -       main_test_on_exit();
>         main_test_backtrace();
>         main_test_libnuma();
>         main_test_timerfd();
> diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
> deleted file mode 100644
> index 8e88b16e6ded..000000000000
> --- a/tools/perf/config/feature-checks/test-on-exit.c
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -#include <stdio.h>
> -#include <stdlib.h>
> -
> -static void exit_fn(int status, void *__data)
> -{
> -       printf("exit status: %d, data: %d\n", status, *(int *)__data);
> -}
> -
> -static int data = 123;
> -
> -int main(void)
> -{
> -       on_exit(exit_fn, &data);
> -
> -       return 321;
> -}
> --
> 1.7.9.2
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
  2014-04-25 13:17   ` Stephane Eranian
@ 2014-04-29 10:56   ` Jiri Olsa
  2014-04-29 11:19     ` Peter Zijlstra
  2014-04-29 11:15   ` Jiri Olsa
  2014-04-29 12:11   ` Peter Zijlstra
  3 siblings, 1 reply; 19+ messages in thread
From: Jiri Olsa @ 2014-04-29 10:56 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra,
	Stephane Eranian, LKML, Namhyung Kim

On Thu, Apr 24, 2014 at 10:27:33PM +0900, Namhyung Kim wrote:

SNIP

> Reported-by: Stephane Eranian <eranian@google.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/builtin-record.c |  121 ++++++++++++++++++-------------------------
>  1 file changed, 51 insertions(+), 70 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index eb524f91bffe..b1523d8a6191 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -152,26 +152,6 @@ static void sig_handler(int sig)
>  	signr = sig;

looks like there's no use for 'signr' now.. could be removed

>  }
>  
> -static void record__sig_exit(int exit_status __maybe_unused, void *arg)
> -{
> -	struct record *rec = arg;
> -	int status;
> -
> -	if (rec->evlist->workload.pid > 0) {
> -		if (!child_finished)
> -			kill(rec->evlist->workload.pid, SIGTERM);
> -
> -		wait(&status);
> -		if (WIFSIGNALED(status))
> -			psignal(WTERMSIG(status), rec->progname);
> -	}
> -
> -	if (signr == -1 || signr == SIGUSR1)
> -		return;
> -
> -	signal(signr, SIG_DFL);

I was wondering what was this one for and found:

  perf_counter tools: Propagate signals properly
  commit f7b7c26e01e51fe46097e11f179dc71ce7950084
  Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
  Date:   Wed Jun 10 15:55:59 2009 +0200

but I dont think we need to do that

thanks,
jirka

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
  2014-04-25 13:17   ` Stephane Eranian
  2014-04-29 10:56   ` Jiri Olsa
@ 2014-04-29 11:15   ` Jiri Olsa
  2014-04-29 12:11   ` Peter Zijlstra
  3 siblings, 0 replies; 19+ messages in thread
From: Jiri Olsa @ 2014-04-29 11:15 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra,
	Stephane Eranian, LKML, Namhyung Kim

On Thu, Apr 24, 2014 at 10:27:33PM +0900, Namhyung Kim wrote:

SNIP

> -		rec->bytes_written / 24);
> +out_child:
> +	if (forks) {
> +		int exit_status;
>  
> -	return 0;
> +		if (!child_finished)
> +			kill(rec->evlist->workload.pid, SIGTERM);

also while at it.. do we want to force SIGKILL in case we dont
get any response for SIGTERM? so we dont get record hanging like
for following program:

---
#include <signal.h>

static void sig_handler(int sig)
{
}

int main(int argc, char **argv)
{
        signal(SIGINT, sig_handler);
        signal(SIGTERM, sig_handler);

        while (1) {}

        return 0;
}
---

the change would go into separate patch of course,
something like in patch below

thanks,
jirka


---
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 526edf5..a973ba5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -479,9 +479,20 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 out_child:
 	if (forks) {
 		int exit_status;
+		int zleep = 0;
+
+		while (!child_finished) {
+			if (!zleep)
+				kill(rec->evlist->workload.pid, SIGTERM);
+			if (zleep == 2000) {
+				pr_info("Child killed by SIGKILL.\n");
+				kill(rec->evlist->workload.pid, SIGKILL);
+				break;
+			}
 
-		if (!child_finished)
-			kill(rec->evlist->workload.pid, SIGTERM);
+			usleep(1000);
+			zleep++;
+		}
 
 		wait(&exit_status);
 

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-29 10:56   ` Jiri Olsa
@ 2014-04-29 11:19     ` Peter Zijlstra
  2014-04-29 11:33       ` Peter Zijlstra
  2014-04-29 11:37       ` Jiri Olsa
  0 siblings, 2 replies; 19+ messages in thread
From: Peter Zijlstra @ 2014-04-29 11:19 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Namhyung Kim, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> 
>   perf_counter tools: Propagate signals properly
>   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
>   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
>   Date:   Wed Jun 10 15:55:59 2009 +0200
> 
> but I dont think we need to do that

But but but, then you're re-introducing that fail again? That no good.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-29 11:19     ` Peter Zijlstra
@ 2014-04-29 11:33       ` Peter Zijlstra
  2014-04-29 11:38         ` Jiri Olsa
  2014-04-29 11:37       ` Jiri Olsa
  1 sibling, 1 reply; 19+ messages in thread
From: Peter Zijlstra @ 2014-04-29 11:33 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Namhyung Kim, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> > 
> >   perf_counter tools: Propagate signals properly
> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
> >   Date:   Wed Jun 10 15:55:59 2009 +0200
> > 
> > but I dont think we need to do that
> 
> But but but, then you're re-introducing that fail again? That no good.

The thing is, just the return value is not sufficient to determine if
the child was interrupted.

See WAIT(2), things like WIFSIGNALED() will not work when you just
propagate the return value, you need to terminate the task with a
signal to propagate this.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-29 11:19     ` Peter Zijlstra
  2014-04-29 11:33       ` Peter Zijlstra
@ 2014-04-29 11:37       ` Jiri Olsa
  2014-04-30  0:24         ` Namhyung Kim
  1 sibling, 1 reply; 19+ messages in thread
From: Jiri Olsa @ 2014-04-29 11:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Namhyung Kim, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> > 
> >   perf_counter tools: Propagate signals properly
> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
> >   Date:   Wed Jun 10 15:55:59 2009 +0200
> > 
> > but I dont think we need to do that
> 
> But but but, then you're re-introducing that fail again? That no good.

well, I was trying the testcase you mentioned in the changelog
and it seemed to work for me.. ;-) I guess I was lucky to hit
the bash time window..

  while :; do perf stat ./foo ; done

so how does this work? bash will kill the loop if perf's wait
status is WIFSIGNALED?

thanks,
jirka

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-29 11:33       ` Peter Zijlstra
@ 2014-04-29 11:38         ` Jiri Olsa
  0 siblings, 0 replies; 19+ messages in thread
From: Jiri Olsa @ 2014-04-29 11:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Namhyung Kim, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Tue, Apr 29, 2014 at 01:33:04PM +0200, Peter Zijlstra wrote:
> On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
> > On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> > > 
> > >   perf_counter tools: Propagate signals properly
> > >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
> > >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
> > >   Date:   Wed Jun 10 15:55:59 2009 +0200
> > > 
> > > but I dont think we need to do that
> > 
> > But but but, then you're re-introducing that fail again? That no good.
> 
> The thing is, just the return value is not sufficient to determine if
> the child was interrupted.
> 
> See WAIT(2), things like WIFSIGNALED() will not work when you just
> propagate the return value, you need to terminate the task with a
> signal to propagate this.
> 

cool, I just asked this in another email ;-) thanks

jirka

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
                     ` (2 preceding siblings ...)
  2014-04-29 11:15   ` Jiri Olsa
@ 2014-04-29 12:11   ` Peter Zijlstra
  3 siblings, 0 replies; 19+ messages in thread
From: Peter Zijlstra @ 2014-04-29 12:11 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Thu, Apr 24, 2014 at 10:27:33PM +0900, Namhyung Kim wrote:
>  static void record__sig_exit(int exit_status __maybe_unused, void *arg)
>  {
> -	struct record *rec = arg;
> -	int status;
> -
> -	if (rec->evlist->workload.pid > 0) {
> -		if (!child_finished)
> -			kill(rec->evlist->workload.pid, SIGTERM);
> -
> -		wait(&status);
> -		if (WIFSIGNALED(status))
> -			psignal(WTERMSIG(status), rec->progname);
> -	}
> -
> -	if (signr == -1 || signr == SIGUSR1)
> +	if (signr == -1)
>  		return;
>  
>  	signal(signr, SIG_DFL);
>  }


> +out_child:
> +	if (forks) {
> +		int exit_status;
>  
> -	return 0;
> +		if (!child_finished)
> +			kill(rec->evlist->workload.pid, SIGTERM);
> +
> +		wait(&exit_status);
> +
> +		if (err < 0)
> +			status = err;
> +		else if (WIFEXITED(exit_status))
> +			status = WEXITSTATUS(exit_status);
> +		else if (WIFSIGNALED(status))
		{
		signr = WTERMSIG(status);
> +			psignal(WTERMSIG(status), rec->progname);
		}
> +	} else
> +		status = err;
> +
> +	if (!err && !file->is_pipe) {
> +		rec->session->header.data_size += rec->bytes_written;
> +
> +		if (!rec->no_buildid)
> +			process_buildids(rec);
> +		perf_session__write_header(rec->session, rec->evlist,
> +					   file->fd, true);
> +	}

Should do I suppose; not sure why the psignal() muck is in there, but it
don't hurt I suppose.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-29 11:37       ` Jiri Olsa
@ 2014-04-30  0:24         ` Namhyung Kim
  2014-05-07 14:00           ` Jiri Olsa
  2014-05-07 15:04           ` Peter Zijlstra
  0 siblings, 2 replies; 19+ messages in thread
From: Namhyung Kim @ 2014-04-30  0:24 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Peter Zijlstra, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

Hi Jiri and Peter,

On Tue, 29 Apr 2014 13:37:47 +0200, Jiri Olsa wrote:
> On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
>> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
>> > 
>> >   perf_counter tools: Propagate signals properly
>> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
>> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
>> >   Date:   Wed Jun 10 15:55:59 2009 +0200
>> > 
>> > but I dont think we need to do that
>> 
>> But but but, then you're re-introducing that fail again? That no good.

FYI, it's already gone with 804f7ac78803 ("perf record: handle death by
SIGTERM").

>
> well, I was trying the testcase you mentioned in the changelog
> and it seemed to work for me.. ;-) I guess I was lucky to hit
> the bash time window..
>
>   while :; do perf stat ./foo ; done
>
> so how does this work? bash will kill the loop if perf's wait
> status is WIFSIGNALED?

I'm not sure but isn't it *bash* to catch signal and terminate the
loop?  It seems the wait status of child has no business with the loop
termination.  Am I missing something?

  $ cat suicide.c
  #include <signal.h>
  
  int main(void)
  {
    raise(SIGTERM);
    return 0;
  }
  
  $ gcc -o suicide suicide.c
  
  $ while :; do ./suicide; done
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  Terminated
  ...


Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [tip:perf/core] perf tools: Handle EINTR error for readn/writen
  2014-04-24 13:27 [PATCH v3 1/3] perf tools: Handle EINTR error for readn/writen Namhyung Kim
  2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
  2014-04-24 13:27 ` [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test Namhyung Kim
@ 2014-05-01  6:30 ` tip-bot for Namhyung Kim
  2 siblings, 0 replies; 19+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-05-01  6:30 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, jolsa, tglx, namhyung

Commit-ID:  e148c76083dc06ce618d768c0bee0a0edda96a54
Gitweb:     http://git.kernel.org/tip/e148c76083dc06ce618d768c0bee0a0edda96a54
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Thu, 24 Apr 2014 22:27:32 +0900
Committer:  Jiri Olsa <jolsa@kernel.org>
CommitDate: Tue, 29 Apr 2014 14:26:30 +0200

perf tools: Handle EINTR error for readn/writen

Those readn/writen functions are to ensure read/write does I/O for
a given size exactly.  But ion() - its implementation - does not
handle in case it returns prematurely due to a signal.  As it's not
an error itself so just retry the operation.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1398346054-3322-1-git-send-email-namhyung@kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/util.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9f66549..7fff6be 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -166,6 +166,8 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 		ssize_t ret = is_read ? read(fd, buf, left) :
 					write(fd, buf, left);
 
+		if (ret < 0 && errno == EINTR)
+			continue;
 		if (ret <= 0)
 			return ret;
 

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-30  0:24         ` Namhyung Kim
@ 2014-05-07 14:00           ` Jiri Olsa
  2014-05-07 15:04           ` Peter Zijlstra
  1 sibling, 0 replies; 19+ messages in thread
From: Jiri Olsa @ 2014-05-07 14:00 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

On Wed, Apr 30, 2014 at 09:24:08AM +0900, Namhyung Kim wrote:
> Hi Jiri and Peter,
> 
> On Tue, 29 Apr 2014 13:37:47 +0200, Jiri Olsa wrote:
> > On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
> >> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> >> > 
> >> >   perf_counter tools: Propagate signals properly
> >> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
> >> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
> >> >   Date:   Wed Jun 10 15:55:59 2009 +0200
> >> > 
> >> > but I dont think we need to do that
> >> 
> >> But but but, then you're re-introducing that fail again? That no good.
> 
> FYI, it's already gone with 804f7ac78803 ("perf record: handle death by
> SIGTERM").

oops, sry for late reply.. I just saw v4

I see, so that kill got deleted, only 'signal(signr, SIG_DFL);' stayed

I think we could take this patch, since it's not introducing regression
(if there's any) in this regard and figure out the bash stuff below later

> 
> >
> > well, I was trying the testcase you mentioned in the changelog
> > and it seemed to work for me.. ;-) I guess I was lucky to hit
> > the bash time window..
> >
> >   while :; do perf stat ./foo ; done
> >
> > so how does this work? bash will kill the loop if perf's wait
> > status is WIFSIGNALED?
> 
> I'm not sure but isn't it *bash* to catch signal and terminate the
> loop?  It seems the wait status of child has no business with the loop
> termination.  Am I missing something?

peterz, any comment? before we start digging in bash.. ;-)

thanks,
jirka

> 
>   $ cat suicide.c
>   #include <signal.h>
>   
>   int main(void)
>   {
>     raise(SIGTERM);
>     return 0;
>   }
>   
>   $ gcc -o suicide suicide.c
>   
>   $ while :; do ./suicide; done
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   Terminated
>   ...
> 
> 
> Thanks,
> Namhyung

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-04-30  0:24         ` Namhyung Kim
  2014-05-07 14:00           ` Jiri Olsa
@ 2014-05-07 15:04           ` Peter Zijlstra
  2014-05-07 17:19             ` Stephane Eranian
  1 sibling, 1 reply; 19+ messages in thread
From: Peter Zijlstra @ 2014-05-07 15:04 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, LKML, Namhyung Kim

[-- Attachment #1: Type: text/plain, Size: 2406 bytes --]

On Wed, Apr 30, 2014 at 09:24:08AM +0900, Namhyung Kim wrote:
> Hi Jiri and Peter,
> 
> On Tue, 29 Apr 2014 13:37:47 +0200, Jiri Olsa wrote:
> > On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
> >> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
> >> > 
> >> >   perf_counter tools: Propagate signals properly
> >> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
> >> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
> >> >   Date:   Wed Jun 10 15:55:59 2009 +0200
> >> > 
> >> > but I dont think we need to do that
> >> 
> >> But but but, then you're re-introducing that fail again? That no good.
> 
> FYI, it's already gone with 804f7ac78803 ("perf record: handle death by
> SIGTERM").
> 
> >
> > well, I was trying the testcase you mentioned in the changelog
> > and it seemed to work for me.. ;-) I guess I was lucky to hit
> > the bash time window..
> >
> >   while :; do perf stat ./foo ; done
> >
> > so how does this work? bash will kill the loop if perf's wait
> > status is WIFSIGNALED?
> 
> I'm not sure but isn't it *bash* to catch signal and terminate the
> loop?  It seems the wait status of child has no business with the loop
> termination.  Am I missing something?
> 
>   $ cat suicide.c
>   #include <signal.h>
>   
>   int main(void)
>   {
>     raise(SIGTERM);
>     return 0;
>   }
>   

SIGTERM isn't the problem. SIGINT is. Typically when you run:

while :; do perf stat ./foo ; done

Its foo that is running, so when you press ^C, you'll SIGINT foo. foo
will then exit, perf stat will notice the exit, exit itself and because
the loop doesn't look at the return value of perf stat, simply
continues.

What I want, and fixed back then, is that if you press ^C foo
terminates, perf stat/record/etc. will finish, but then terminate with
the same signal. In that case bash finally sees the SIGINT and will in
fact terminate the loop.

try:

$ while :; do ./foo /bin/sleep 5 ; done

and try and break out using ^C

---
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[], char *envp[])
{
	pid_t pid = fork();
	if (!pid) /* child */ {
		execve(argv[1], argv+1, envp);
		perror("execve");
		return;
	}

	signal(SIGINT, SIG_IGN);
	waitpid(pid, NULL, 0);
	return 0;
}

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-05-07 15:04           ` Peter Zijlstra
@ 2014-05-07 17:19             ` Stephane Eranian
  2014-05-07 17:35               ` Peter Zijlstra
  0 siblings, 1 reply; 19+ messages in thread
From: Stephane Eranian @ 2014-05-07 17:19 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Namhyung Kim, Jiri Olsa, Arnaldo Carvalho de Melo, Ingo Molnar,
	LKML, Namhyung Kim

On Wed, May 7, 2014 at 5:04 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Wed, Apr 30, 2014 at 09:24:08AM +0900, Namhyung Kim wrote:
>> Hi Jiri and Peter,
>>
>> On Tue, 29 Apr 2014 13:37:47 +0200, Jiri Olsa wrote:
>> > On Tue, Apr 29, 2014 at 01:19:39PM +0200, Peter Zijlstra wrote:
>> >> On Tue, Apr 29, 2014 at 12:56:54PM +0200, Jiri Olsa wrote:
>> >> >
>> >> >   perf_counter tools: Propagate signals properly
>> >> >   commit f7b7c26e01e51fe46097e11f179dc71ce7950084
>> >> >   Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
>> >> >   Date:   Wed Jun 10 15:55:59 2009 +0200
>> >> >
>> >> > but I dont think we need to do that
>> >>
>> >> But but but, then you're re-introducing that fail again? That no good.
>>
>> FYI, it's already gone with 804f7ac78803 ("perf record: handle death by
>> SIGTERM").
>>
>> >
>> > well, I was trying the testcase you mentioned in the changelog
>> > and it seemed to work for me.. ;-) I guess I was lucky to hit
>> > the bash time window..
>> >
>> >   while :; do perf stat ./foo ; done
>> >
>> > so how does this work? bash will kill the loop if perf's wait
>> > status is WIFSIGNALED?
>>
>> I'm not sure but isn't it *bash* to catch signal and terminate the
>> loop?  It seems the wait status of child has no business with the loop
>> termination.  Am I missing something?
>>
>>   $ cat suicide.c
>>   #include <signal.h>
>>
>>   int main(void)
>>   {
>>     raise(SIGTERM);
>>     return 0;
>>   }
>>
>
> SIGTERM isn't the problem. SIGINT is. Typically when you run:
>
> while :; do perf stat ./foo ; done
>
> Its foo that is running, so when you press ^C, you'll SIGINT foo. foo
> will then exit, perf stat will notice the exit, exit itself and because
> the loop doesn't look at the return value of perf stat, simply
> continues.
>
> What I want, and fixed back then, is that if you press ^C foo
> terminates, perf stat/record/etc. will finish, but then terminate with
> the same signal. In that case bash finally sees the SIGINT and will in
> fact terminate the loop.
>
> try:
>
> $ while :; do ./foo /bin/sleep 5 ; done
>
> and try and break out using ^C
>
What I usually do here is hit ^Z, then kill the job.
But I agree it would be nicer to handle this case automatically.

> ---
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <signal.h>
> #include <sys/types.h>
> #include <sys/wait.h>
>
> int main(int argc, char *argv[], char *envp[])
> {
>         pid_t pid = fork();
>         if (!pid) /* child */ {
>                 execve(argv[1], argv+1, envp);
>                 perror("execve");
>                 return;
>         }
>
>         signal(SIGINT, SIG_IGN);
>         waitpid(pid, NULL, 0);
>         return 0;
> }

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-05-07 17:19             ` Stephane Eranian
@ 2014-05-07 17:35               ` Peter Zijlstra
  2014-05-08  7:49                 ` Namhyung Kim
  0 siblings, 1 reply; 19+ messages in thread
From: Peter Zijlstra @ 2014-05-07 17:35 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: Namhyung Kim, Jiri Olsa, Arnaldo Carvalho de Melo, Ingo Molnar,
	LKML, Namhyung Kim

[-- Attachment #1: Type: text/plain, Size: 644 bytes --]

On Wed, May 07, 2014 at 07:19:14PM +0200, Stephane Eranian wrote:
> > $ while :; do ./foo /bin/sleep 5 ; done
> >
> > and try and break out using ^C
> >
> What I usually do here is hit ^Z, then kill the job.
> But I agree it would be nicer to handle this case automatically.

So that used to work. And note that if you take out the signal(SIGINT,
SIG_IGN) from the proglet, it will actually propagate the SIGINT and
work as expected.

So its only because perf handles SIGINT -- to be able to finish the
stat/data record, that it doesn't. Which is why I propagated the signal
the child got killed with.

Now apparently someone broke that again.

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 2/3] perf record: Propagate exit status of a command line workload
  2014-05-07 17:35               ` Peter Zijlstra
@ 2014-05-08  7:49                 ` Namhyung Kim
  0 siblings, 0 replies; 19+ messages in thread
From: Namhyung Kim @ 2014-05-08  7:49 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Stephane Eranian, Jiri Olsa, Arnaldo Carvalho de Melo,
	Ingo Molnar, LKML, Namhyung Kim

Hi Peter,

On Wed, 7 May 2014 19:35:32 +0200, Peter Zijlstra wrote:
> On Wed, May 07, 2014 at 07:19:14PM +0200, Stephane Eranian wrote:
>> > $ while :; do ./foo /bin/sleep 5 ; done
>> >
>> > and try and break out using ^C
>> >
>> What I usually do here is hit ^Z, then kill the job.
>> But I agree it would be nicer to handle this case automatically.
>
> So that used to work. And note that if you take out the signal(SIGINT,
> SIG_IGN) from the proglet, it will actually propagate the SIGINT and
> work as expected.
>
> So its only because perf handles SIGINT -- to be able to finish the
> stat/data record, that it doesn't. Which is why I propagated the signal
> the child got killed with.

Ah, okay.  But just propagating saved signal looks not enough since it's
overwritten by SIGCHLD as child exited.  I'll resend v5 soon.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-05-08  7:49 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-24 13:27 [PATCH v3 1/3] perf tools: Handle EINTR error for readn/writen Namhyung Kim
2014-04-24 13:27 ` [PATCH v3 2/3] perf record: Propagate exit status of a command line workload Namhyung Kim
2014-04-25 13:17   ` Stephane Eranian
2014-04-29 10:56   ` Jiri Olsa
2014-04-29 11:19     ` Peter Zijlstra
2014-04-29 11:33       ` Peter Zijlstra
2014-04-29 11:38         ` Jiri Olsa
2014-04-29 11:37       ` Jiri Olsa
2014-04-30  0:24         ` Namhyung Kim
2014-05-07 14:00           ` Jiri Olsa
2014-05-07 15:04           ` Peter Zijlstra
2014-05-07 17:19             ` Stephane Eranian
2014-05-07 17:35               ` Peter Zijlstra
2014-05-08  7:49                 ` Namhyung Kim
2014-04-29 11:15   ` Jiri Olsa
2014-04-29 12:11   ` Peter Zijlstra
2014-04-24 13:27 ` [PATCH v3 3/3] perf tools: Get rid of on_exit() feature test Namhyung Kim
2014-04-25 13:18   ` Stephane Eranian
2014-05-01  6:30 ` [tip:perf/core] perf tools: Handle EINTR error for readn/writen tip-bot for Namhyung Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).