Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
55cca82
added features for runsolver/starexec compatibility
geoffgeoffgeoff3 Oct 28, 2025
0638db1
syntax fix for Ruff
geoffgeoffgeoff3 Oct 28, 2025
b5d3563
syntax fix for Ruff
geoffgeoffgeoff3 Oct 28, 2025
62d38ef
syntax fix for Ruff
geoffgeoffgeoff3 Oct 28, 2025
fa4eb4a
fixed ^C, added option for output to stdout
geoffgeoffgeoff3 Oct 28, 2025
2577b8b
fix for Ruff
geoffgeoffgeoff3 Oct 28, 2025
3ec4025
fix for Ruff
geoffgeoffgeoff3 Oct 28, 2025
8771788
added flag to send statistics to a file instead of stdout
geoffgeoffgeoff3 Oct 28, 2025
c0bb2d6
fix for Ruff
geoffgeoffgeoff3 Oct 29, 2025
fee787b
fixed so no piping if no timestamps. working on container version but…
geoffgeoffgeoff3 Oct 29, 2025
12fdc16
soft wall clock limit implemented
geoffgeoffgeoff3 Oct 30, 2025
e8e0dd1
fixes for Ruff
geoffgeoffgeoff3 Oct 30, 2025
b0b4491
Final version (I hope) with original containerexecutor.py
geoffgeoffgeoff3 Oct 30, 2025
27d29ea
Final version fix for Ruff
geoffgeoffgeoff3 Oct 30, 2025
c4dfa83
Final version fix for Ruff
geoffgeoffgeoff3 Oct 30, 2025
365bff7
Put back original containerexecutor.py
geoffgeoffgeoff3 Oct 30, 2025
7ad4a34
branch for working on container timestamps
geoffgeoffgeoff3 Oct 30, 2025
84afb6a
container timestamps
geoffgeoffgeoff3 Oct 30, 2025
cb8b04b
Merge branch 'timestamps_and_more' into runsolver_compatible
geoffgeoffgeoff3 Oct 30, 2025
8da5e01
checked timestamp if add-eof
geoffgeoffgeoff3 Oct 30, 2025
72e17bb
tidy timestamps
geoffgeoffgeoff3 Oct 30, 2025
c5ab2d6
Ruff-ians
geoffgeoffgeoff3 Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions benchexec/baseexecutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import errno
import logging
import os
import time
import subprocess
import sys
import threading
Expand Down Expand Up @@ -66,6 +67,8 @@ def _start_execution(
stdin,
stdout,
stderr,
timestamp,
addeof,
env,
cwd,
temp_dir,
Expand All @@ -75,6 +78,7 @@ def _start_execution(
parent_cleanup_fn,
):
"""Actually start the tool and the measurements.
@param args: the command line to run
@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
Expand Down Expand Up @@ -114,15 +118,18 @@ def pre_subprocess():
p = subprocess.Popen(
args,
stdin=stdin,
stdout=stdout,
stderr=stderr,
stdout=(subprocess.PIPE if timestamp else stdout),
stderr=(subprocess.STDOUT if timestamp else stderr),
env=env,
cwd=cwd,
close_fds=True,
preexec_fn=pre_subprocess,
text=True,
)

def wait_and_get_result():
if timestamp:
self._add_timestamps_and_EOF(cgroups,p.stdout,parent_setup[1],addeof)
exitcode, ru_child = self._wait_for_process(p.pid, args[0])
p.poll()

Expand All @@ -133,6 +140,16 @@ def wait_and_get_result():

return p.pid, cgroups, wait_and_get_result

def _add_timestamps_and_EOF(self,cgroups,tool_stdout,time_started,addeof):
for line in tool_stdout:
CPU = cgroups.read_cputime()
WC = time.monotonic() - time_started
print(f"{CPU:.4f}/{WC:.4f}\t{line.strip()}")
if addeof:
CPU = cgroups.read_cputime()
WC = time.monotonic() - time_started
print(f"{CPU:.4f}/{WC:.4f}\tEOF")

def _wait_for_process(self, pid, name):
"""Wait for the given process to terminate.
@return tuple of exit code and resource usage
Expand Down
23 changes: 18 additions & 5 deletions benchexec/containerexecutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@ def _start_execution_in_container(
stdin,
stdout,
stderr,
timestamp,
addeof,
env,
root_dir,
cwd,
Expand Down Expand Up @@ -610,6 +612,8 @@ def _start_execution_in_container(
from_parent, to_grandchild = os.pipe()
# "upstream" pipe grandchild/child->parent
from_grandchild, to_parent = os.pipe()
# "upstream" stdout/stderr pipe grandchild/child->parent
stdout_from_grandchild, stdout_to_grandparent = os.pipe()

# The protocol for these pipes is that first the parent sends the marker for
# user mappings, then the grand child sends its outer PID back,
Expand Down Expand Up @@ -644,7 +648,6 @@ def grandchild():
# and reading /proc/self in the outer procfs instance
# (that's what we do).
my_outer_pid = container.get_my_pid_from_procfs()

container.mount_proc(self._container_system_config)
container.reset_signal_handling()
child_setup_fn() # Do some other setup the caller wants.
Expand Down Expand Up @@ -676,6 +679,7 @@ def grandchild():
raise
finally:
# close remaining ends of pipe
os.close(stdout_from_grandchild)
os.close(from_parent)
os.close(to_parent)
# here Python will exec() the tool for us
Expand Down Expand Up @@ -709,6 +713,7 @@ def child():
stdin,
stdout,
stderr,
stdout_to_grandparent,
} - {None}
container.close_open_fds(keep_files=necessary_fds)

Expand Down Expand Up @@ -774,11 +779,11 @@ def child():
container.setup_seccomp_filter()

try:
grandchild_proc = subprocess.Popen(
grandchild_proc = subprocess.Popen( # This is in the child
args,
stdin=stdin,
stdout=stdout,
stderr=stderr,
stdout=(stdout_to_grandparent if timestamp else stdout),
stderr=(subprocess.STDOUT if timestamp else stderr),
env=env,
close_fds=False,
preexec_fn=grandchild,
Expand All @@ -787,6 +792,9 @@ def child():
logging.critical("Cannot start process: %s", e)
return CHILD_OSERROR

# stdout_from_grandchild was closed earlier
os.close(stdout_to_grandparent)

# keep capability for unmount if necessary later
necessary_capabilities = (
[libc.CAP_SYS_ADMIN] if result_files_patterns else []
Expand Down Expand Up @@ -930,6 +938,7 @@ def check_child_exit_code():
# if all other processes have terminated.
os.close(from_parent)
os.close(to_parent)
os.close(stdout_to_grandparent)

container.setup_user_mapping(child_pid, uid=self._uid, gid=self._gid)
# signal child to continue
Expand Down Expand Up @@ -1009,7 +1018,11 @@ def check_child_exit_code():
os.close(from_grandchild)
os.close(to_grandchild)

def wait_for_grandchild():
def wait_for_grandchild(): # This is in the parent
if timestamp:
read_from_grandchild = os.fdopen(stdout_from_grandchild, 'r', encoding='utf-8')
self._add_timestamps_and_EOF(cgroups,read_from_grandchild,parent_setup[1],addeof)
os.close(stdout_from_grandchild)
# 1024 bytes ought to be enough for everyone^Wour pickled result
try:
received = os.read(from_grandchild_copy, 1024)
Expand Down
Loading
Loading