Skip to content

Commit

Permalink
Support fractional seconds for files_timeout
Browse files Browse the repository at this point in the history
This will be helpful in testing, since some machines are able to
process quite a lot in one second, which was the previous lowest
timeout.
  • Loading branch information
MarkKoz committed Sep 16, 2023
1 parent 2fb4d67 commit 4d299c1
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 5 deletions.
5 changes: 3 additions & 2 deletions snekbox/nsjail.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import subprocess
import sys
from collections.abc import Generator
from contextlib import nullcontext
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Iterable, TypeVar
Expand Down Expand Up @@ -56,7 +57,7 @@ def __init__(
memfs_home: str = "home",
memfs_output: str = "home",
files_limit: int | None = 100,
files_timeout: int | None = 5,
files_timeout: float | None = 5,
files_pattern: str = "**/[!_]*",
):
"""
Expand Down Expand Up @@ -267,7 +268,7 @@ def python3(

# Parse attachments with time limit
try:
with time_limit(self.files_timeout):
with time_limit(self.files_timeout) if self.files_timeout else nullcontext():
attachments = fs.files_list(
limit=self.files_limit,
pattern=self.files_pattern,
Expand Down
8 changes: 5 additions & 3 deletions snekbox/utils/timed.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


@contextmanager
def time_limit(timeout: int | None = None) -> Generator[None, None, None]:
def time_limit(timeout: float) -> Generator[None, None, None]:
"""
Decorator to call a function with a time limit.
Expand All @@ -25,10 +25,12 @@ def time_limit(timeout: int | None = None) -> Generator[None, None, None]:
def signal_handler(_signum, _frame):
raise TimeoutError(f"time_limit call timed out after {timeout} seconds.")

# ITIMER_PROF would be more appropriate, but SIGPROF doesn't seem to interrupt sleeps.
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(timeout)
signal.setitimer(signal.ITIMER_REAL, timeout)

try:
yield
finally:
signal.alarm(0)
# Clear the timer if the function finishes early.
signal.setitimer(signal.ITIMER_REAL, 0)

0 comments on commit 4d299c1

Please sign in to comment.