perf evlist: Enhance perf_evlist__start_workload()
authorNamhyung Kim <[email protected]>
Wed, 26 Jun 2013 07:14:15 +0000 (16:14 +0900)
committerArnaldo Carvalho de Melo <[email protected]>
Mon, 8 Jul 2013 20:38:30 +0000 (17:38 -0300)
When perf tries to start a workload, it relies on a pipe which the
workload was blocked for reading.  After closing the pipe on the parent,
the workload (child) can start the actual work via exec().

However, if another process was forked after creating a workload, this
mechanism cannot work since the other process (child) also inherits the
pipe, so that closing the pipe in parent cannot unblock the workload.
Fix it by using explicit write call can then closing it.

For similar reason, the pipe fd on parent should be marked as CLOEXEC so
that it can be closed after another child exec'ed.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
tools/perf/util/evlist.c

index 99b43dd18c57faf34598ae9b777327b048dab9f0..8065ce8fa9a5cdaea730e55667b7c5ed1d9b77f9 100644 (file)
@@ -821,6 +821,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
                goto out_close_pipes;
        }
 
+       fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
        evlist->workload.cork_fd = go_pipe[1];
        close(child_ready_pipe[0]);
        return 0;
@@ -837,10 +838,17 @@ out_close_ready_pipe:
 int perf_evlist__start_workload(struct perf_evlist *evlist)
 {
        if (evlist->workload.cork_fd > 0) {
+               char bf;
+               int ret;
                /*
                 * Remove the cork, let it rip!
                 */
-               return close(evlist->workload.cork_fd);
+               ret = write(evlist->workload.cork_fd, &bf, 1);
+               if (ret < 0)
+                       perror("enable to write to pipe");
+
+               close(evlist->workload.cork_fd);
+               return ret;
        }
 
        return 0;