static unsigned int            page_size;
 static unsigned int            mmap_pages                      = UINT_MAX;
 static int                     output;
-static int                     pipe_output                     =      0;
 static const char              *output_name                    = NULL;
 static bool                    group                           =  false;
 static int                     realtime_prio                   =      0;
-static pid_t                   child_pid                       =     -1;
 static enum write_mode_t       write_mode                      = WRITE_FORCE;
 static bool                    no_buildid                      =  false;
 static bool                    no_buildid_cache                =  false;
 {
        int status;
 
-       if (child_pid > 0) {
+       if (evsel_list->workload.pid > 0) {
                if (!child_finished)
-                       kill(child_pid, SIGTERM);
+                       kill(evsel_list->workload.pid, SIGTERM);
 
                wait(&status);
                if (WIFSIGNALED(status))
 
 static void atexit_header(void)
 {
-       if (!pipe_output) {
+       if (!record_opts.pipe_output) {
                session->header.data_size += bytes_written;
 
                if (!no_buildid)
        int flags;
        int err;
        unsigned long waking = 0;
-       int child_ready_pipe[2], go_pipe[2];
        const bool forks = argc > 0;
-       char buf;
        struct machine *machine;
 
        progname = argv[0];
        signal(SIGINT, sig_handler);
        signal(SIGUSR1, sig_handler);
 
-       if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
-               perror("failed to create pipes");
-               exit(-1);
-       }
-
        if (!output_name) {
                if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
-                       pipe_output = true;
+                       record_opts.pipe_output = true;
                else
                        output_name = "perf.data";
        }
        if (output_name) {
                if (!strcmp(output_name, "-"))
-                       pipe_output = true;
+                       record_opts.pipe_output = true;
                else if (!stat(output_name, &st) && st.st_size) {
                        if (write_mode == WRITE_FORCE) {
                                char oldname[PATH_MAX];
        else
                flags |= O_TRUNC;
 
-       if (pipe_output)
+       if (record_opts.pipe_output)
                output = STDOUT_FILENO;
        else
                output = open(output_name, flags, S_IRUSR | S_IWUSR);
                mmap_pages = (512 * 1024) / page_size;
 
        if (forks) {
-               child_pid = fork();
-               if (child_pid < 0) {
-                       perror("failed to fork");
-                       exit(-1);
-               }
-
-               if (!child_pid) {
-                       if (pipe_output)
-                               dup2(2, 1);
-                       close(child_ready_pipe[0]);
-                       close(go_pipe[1]);
-                       fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
-
-                       /*
-                        * Do a dummy execvp to get the PLT entry resolved,
-                        * so we avoid the resolver overhead on the real
-                        * execvp call.
-                        */
-                       execvp("", (char **)argv);
-
-                       /*
-                        * Tell the parent we're ready to go
-                        */
-                       close(child_ready_pipe[1]);
-
-                       /*
-                        * Wait until the parent tells us to go.
-                        */
-                       if (read(go_pipe[0], &buf, 1) == -1)
-                               perror("unable to read pipe");
-
-                       execvp(argv[0], (char **)argv);
-
-                       perror(argv[0]);
-                       kill(getppid(), SIGUSR1);
-                       exit(-1);
-               }
-
-               if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
-                       evsel_list->threads->map[0] = child_pid;
-
-               close(child_ready_pipe[1]);
-               close(go_pipe[0]);
-               /*
-                * wait for child to settle
-                */
-               if (read(child_ready_pipe[0], &buf, 1) == -1) {
-                       perror("unable to read pipe");
-                       exit(-1);
+               err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
+               if (err < 0) {
+                       pr_err("Couldn't run the workload!\n");
+                       goto out_delete_session;
                }
-               close(child_ready_pipe[0]);
        }
 
        open_counters(evsel_list);
         */
        atexit(atexit_header);
 
-       if (pipe_output) {
+       if (record_opts.pipe_output) {
                err = perf_header__write_pipe(output);
                if (err < 0)
                        return err;
 
        post_processing_offset = lseek(output, 0, SEEK_CUR);
 
-       if (pipe_output) {
+       if (record_opts.pipe_output) {
                err = perf_session__synthesize_attrs(session,
                                                     process_synthesized_event);
                if (err < 0) {
         * Let the child rip
         */
        if (forks)
-               close(go_pipe[1]);
+               perf_evlist__start_workload(evsel_list);
 
        for (;;) {
                int hits = samples;
 
 #include "thread_map.h"
 #include "evlist.h"
 #include "evsel.h"
+#include <unistd.h>
 
 #include "parse-events.h"
 
                INIT_HLIST_HEAD(&evlist->heads[i]);
        INIT_LIST_HEAD(&evlist->entries);
        perf_evlist__set_maps(evlist, cpus, threads);
+       evlist->workload.pid = -1;
 }
 
 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
 
        return err;
 }
+
+int perf_evlist__prepare_workload(struct perf_evlist *evlist,
+                                 struct perf_record_opts *opts,
+                                 const char *argv[])
+{
+       int child_ready_pipe[2], go_pipe[2];
+       char bf;
+
+       if (pipe(child_ready_pipe) < 0) {
+               perror("failed to create 'ready' pipe");
+               return -1;
+       }
+
+       if (pipe(go_pipe) < 0) {
+               perror("failed to create 'go' pipe");
+               goto out_close_ready_pipe;
+       }
+
+       evlist->workload.pid = fork();
+       if (evlist->workload.pid < 0) {
+               perror("failed to fork");
+               goto out_close_pipes;
+       }
+
+       if (!evlist->workload.pid) {
+               if (opts->pipe_output)
+                       dup2(2, 1);
+
+               close(child_ready_pipe[0]);
+               close(go_pipe[1]);
+               fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
+
+               /*
+                * Do a dummy execvp to get the PLT entry resolved,
+                * so we avoid the resolver overhead on the real
+                * execvp call.
+                */
+               execvp("", (char **)argv);
+
+               /*
+                * Tell the parent we're ready to go
+                */
+               close(child_ready_pipe[1]);
+
+               /*
+                * Wait until the parent tells us to go.
+                */
+               if (read(go_pipe[0], &bf, 1) == -1)
+                       perror("unable to read pipe");
+
+               execvp(argv[0], (char **)argv);
+
+               perror(argv[0]);
+               kill(getppid(), SIGUSR1);
+               exit(-1);
+       }
+
+       if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
+               evlist->threads->map[0] = evlist->workload.pid;
+
+       close(child_ready_pipe[1]);
+       close(go_pipe[0]);
+       /*
+        * wait for child to settle
+        */
+       if (read(child_ready_pipe[0], &bf, 1) == -1) {
+               perror("unable to read pipe");
+               goto out_close_pipes;
+       }
+
+       evlist->workload.cork_fd = go_pipe[1];
+       close(child_ready_pipe[0]);
+       return 0;
+
+out_close_pipes:
+       close(go_pipe[0]);
+       close(go_pipe[1]);
+out_close_ready_pipe:
+       close(child_ready_pipe[0]);
+       close(child_ready_pipe[1]);
+       return -1;
+}
+
+int perf_evlist__start_workload(struct perf_evlist *evlist)
+{
+       if (evlist->workload.cork_fd > 0) {
+               /*
+                * Remove the cork, let it rip!
+                */
+               return close(evlist->workload.cork_fd);
+       }
+
+       return 0;
+}