Actually start the tool and the measurements.
        @param parent_setup_fn a function without parameters that is called in the parent process
            immediately before the tool is started
        @param child_setup_fn a function without parameters that is called in the child process
            before the tool is started
        @param parent_cleanup_fn a function that is called in the parent process
            immediately after the tool terminated, with three parameters:
            the result of parent_setup_fn, the result of the executed process as ProcessExitCode,
            and the base path for looking up files as parameter values
        @return: a tuple of PID of process and a blocking function, which waits for the process
            and a triple of the exit code and the resource usage of the process
            and the result of parent_cleanup_fn (do not use os.wait)

def _start_execution(self, args, stdin, stdout, stderr, env, cwd, temp_dir, cgroups,
                         parent_setup_fn, child_setup_fn, parent_cleanup_fn):
        """Actually start the tool and the measurements.
        @param parent_setup_fn a function without parameters that is called in the parent process
            immediately before the tool is started
        @param child_setup_fn a function without parameters that is called in the child process
            before the tool is started
        @param parent_cleanup_fn a function that is called in the parent process
            immediately after the tool terminated, with three parameters:
            the result of parent_setup_fn, the result of the executed process as ProcessExitCode,
            and the base path for looking up files as parameter values
        @return: a tuple of PID of process and a blocking function, which waits for the process
            and a triple of the exit code and the resource usage of the process
            and the result of parent_cleanup_fn (do not use os.wait)
        """
        def pre_subprocess():
            # Do some other setup the caller wants.
            child_setup_fn()

            # put us into the cgroup(s)
            pid = os.getpid()
            cgroups.add_task(pid)

        # Set HOME and TMPDIR to fresh directories.
        tmp_dir = os.path.join(temp_dir, "tmp")
        home_dir = os.path.join(temp_dir, "home")
        self._create_dirs_in_temp_dir(tmp_dir, home_dir)
        env["HOME"] = home_dir
        env["TMPDIR"] = tmp_dir
        env["TMP"] = tmp_dir
        env["TEMPDIR"] = tmp_dir
        env["TEMP"] = tmp_dir
        logging.debug("Executing run with $HOME and $TMPDIR below %s.", temp_dir)

        args = self._build_cmdline(args, env=env)

        parent_setup = parent_setup_fn()

        p = subprocess.Popen(args,
                     stdin=stdin,
                     stdout=stdout, stderr=stderr,
                     env=env, cwd=cwd,
                     close_fds=True,
                     preexec_fn=pre_subprocess)

        def wait_and_get_result():
            exitcode, ru_child = self._wait_for_process(p.pid, args[0])

            parent_cleanup = parent_cleanup_fn(
                parent_setup, util.ProcessExitCode.from_raw(exitcode), "")
            return exitcode, ru_child, parent_cleanup

        return p.pid, wait_and_get_result