This function executes a given command with resource limits,
        and writes the output to a file.
        @param args: the command line to run
        @param output_filename: the file where the output should be written to
        @param stdin: What to uses as stdin for the process (None: /dev/null, a file descriptor, or a file object)
        @param hardtimelimit: None or the CPU time in seconds after which the tool is forcefully killed.
        @param softtimelimit: None or the CPU time in seconds after which the tool is sent a kill signal.
        @param walltimelimit: None or the wall time in seconds after which the tool is forcefully killed (default: hardtimelimit + a few seconds)
        @param cores: None or a list of the CPU cores to use
        @param memlimit: None or memory limit in bytes
        @param memory_nodes: None or a list of memory nodes in a NUMA system to use
        @param environments: special environments for running the command
        @param workingDir: None or a directory which the execution should use as working directory
        @param maxLogfileSize: None or a number of bytes to which the output of the tool should be truncated approximately if there is too much output.
        @param cgroupValues: dict of additional cgroup values to set (key is tuple of subsystem and option, respective subsystem needs to be enabled in RunExecutor; cannot be used to override values set by BenchExec)
        @param files_count_limit: None or maximum number of files that may be written.
        @param files_size_limit: None or maximum size of files that may be written.
        @param error_filename: the file where the error output should be written to (default: same as output_filename)
        @param write_headers: Write informational headers to the output and the error file if separate (default: True)
        @param **kwargs: further arguments for ContainerExecutor.execute_run()
        @return: dict with result of run (measurement results and process exitcode)

def execute_run(self, args, output_filename, stdin=None,
                    hardtimelimit=None, softtimelimit=None, walltimelimit=None,
                   cores=None, memlimit=None, memory_nodes=None,
                   environments={}, workingDir=None, maxLogfileSize=None,
                   cgroupValues={},
                   files_count_limit=None, files_size_limit=None,
                   error_filename=None, write_header=True,
                   **kwargs):
        """
        This function executes a given command with resource limits,
        and writes the output to a file.
        @param args: the command line to run
        @param output_filename: the file where the output should be written to
        @param stdin: What to uses as stdin for the process (None: /dev/null, a file descriptor, or a file object)
        @param hardtimelimit: None or the CPU time in seconds after which the tool is forcefully killed.
        @param softtimelimit: None or the CPU time in seconds after which the tool is sent a kill signal.
        @param walltimelimit: None or the wall time in seconds after which the tool is forcefully killed (default: hardtimelimit + a few seconds)
        @param cores: None or a list of the CPU cores to use
        @param memlimit: None or memory limit in bytes
        @param memory_nodes: None or a list of memory nodes in a NUMA system to use
        @param environments: special environments for running the command
        @param workingDir: None or a directory which the execution should use as working directory
        @param maxLogfileSize: None or a number of bytes to which the output of the tool should be truncated approximately if there is too much output.
        @param cgroupValues: dict of additional cgroup values to set (key is tuple of subsystem and option, respective subsystem needs to be enabled in RunExecutor; cannot be used to override values set by BenchExec)
        @param files_count_limit: None or maximum number of files that may be written.
        @param files_size_limit: None or maximum size of files that may be written.
        @param error_filename: the file where the error output should be written to (default: same as output_filename)
        @param write_headers: Write informational headers to the output and the error file if separate (default: True)
        @param **kwargs: further arguments for ContainerExecutor.execute_run()
        @return: dict with result of run (measurement results and process exitcode)
        """
        # Check argument values and call the actual method _execute()

        if stdin == subprocess.PIPE:
            sys.exit('Illegal value subprocess.PIPE for stdin')
        elif stdin is None:
            stdin = DEVNULL

        if hardtimelimit is not None:
            if hardtimelimit <= 0:
                sys.exit("Invalid time limit {0}.".format(hardtimelimit))
        if softtimelimit is not None:
            if softtimelimit <= 0:
                sys.exit("Invalid soft time limit {0}.".format(softtimelimit))
            if hardtimelimit and (softtimelimit > hardtimelimit):
                sys.exit("Soft time limit cannot be larger than the hard time limit.")
            if not CPUACCT in self.cgroups:
                sys.exit("Soft time limit cannot be specified without cpuacct cgroup.")

        if walltimelimit is None:
            if hardtimelimit is not None:
                walltimelimit = hardtimelimit + _WALLTIME_LIMIT_DEFAULT_OVERHEAD
            elif softtimelimit is not None:
                walltimelimit = softtimelimit + _WALLTIME_LIMIT_DEFAULT_OVERHEAD
        else:
            if walltimelimit <= 0:
                sys.exit("Invalid wall time limit {0}.".format(walltimelimit))

        if cores is not None:
            if self.cpus is None:
                sys.exit("Cannot limit CPU cores without cpuset cgroup.")
            if not cores:
                sys.exit("Cannot execute run without any CPU core.")
            if not set(cores).issubset(self.cpus):
                sys.exit("Cores {0} are not allowed to be used".format(list(set(cores).difference(self.cpus))))

        if memlimit is not None:
            if memlimit <= 0:
                sys.exit("Invalid memory limit {0}.".format(memlimit))
            if not MEMORY in self.cgroups:
                sys.exit("Memory limit specified, but cannot be implemented without cgroup support.")

        if memory_nodes is not None:
            if self.memory_nodes is None:
                sys.exit("Cannot restrict memory nodes without cpuset cgroup.")
            if len(memory_nodes) == 0:
                sys.exit("Cannot execute run without any memory node.")
            if not set(memory_nodes).issubset(self.memory_nodes):
                sys.exit("Memory nodes {0} are not allowed to be used".format(list(set(memory_nodes).difference(self.memory_nodes))))

        if workingDir:
            if not os.path.exists(workingDir):
                sys.exit("Working directory {0} does not exist.".format(workingDir))
            if not os.path.isdir(workingDir):
                sys.exit("Working directory {0} is not a directory.".format(workingDir))
            if not os.access(workingDir, os.X_OK):
                sys.exit("Permission denied for working directory {0}.".format(workingDir))

        for ((subsystem, option), _) in cgroupValues.items():
            if not subsystem in self._cgroup_subsystems:
                sys.exit('Cannot set option "{option}" for subsystem "{subsystem}" that is not enabled. '
                         'Please specify "--require-cgroup-subsystem {subsystem}".'.format(
                            option=option, subsystem=subsystem))
            if not self.cgroups.has_value(subsystem, option):
                sys.exit('Cannot set option "{option}" for subsystem "{subsystem}", it does not exist.'
                         .format(option=option, subsystem=subsystem))

        if files_count_limit is not None:
            if files_count_limit < 0:
                sys.exit("Invalid files-count limit {0}.".format(files_count_limit))
        if files_size_limit is not None:
            if files_size_limit < 0:
                sys.exit("Invalid files-size limit {0}.".format(files_size_limit))

        try:
            return self._execute(args, output_filename, error_filename, stdin, write_header,
                                 hardtimelimit, softtimelimit, walltimelimit, memlimit,
                                 cores, memory_nodes,
                                 cgroupValues,
                                 environments, workingDir, maxLogfileSize,
                                 files_count_limit, files_size_limit,
                                 **kwargs)

        except BenchExecException as e:
            logging.critical("Cannot execute '%s': %s.",
                util.escape_string_shell(args[0]), e)
            return {'terminationreason': 'failed', 'exitcode': 0,
                    'cputime': 0, 'walltime': 0}
        except OSError as e:
            logging.critical("OSError %s while starting '%s' in '%s': %s.",
                e.errno, util.escape_string_shell(args[0]), workingDir or '.', e.strerror)
            return {'terminationreason': 'failed', 'exitcode': 0,
                    'cputime': 0, 'walltime': 0}