fix return-value/deprecated API bugs, accumulation lock leaks, code cleanup
Build Debian Packages / build (bookworm, debian12) (push) Successful in 8m56s
Build Debian Packages / build (trixie, debian13) (push) Successful in 9m3s

- raise instead of silent None for unsupported operands and empty negation
- validate before acquiring lock in Accumulation operators (no RLock leak)
- Accumulation._copy_provenance helper, ADC_Result._copy_metadata for all result paths
- shared _sandbox_stdout_redirect contextmanager for sandboxed scripts
- TemperatureMonitor dead code removal (gtk helper, traceback, unused properties)
- new unit tests incl. lock-freedom regression test
- gitignore sphinx generated doc/_autosummary/ and doc/damaris/
This commit is contained in:
markusro committed 2026-10-17 19:17:43 +02:00
1 parent 91ade4376c
commit f9d8de7697
26 files changed
+590 -236

No files matched your search

+27 -16
View File
@@ -5,6 +5,7 @@ import sys
import time
import logging
import ast
import contextlib
from damaris.experiments.Experiment import Quit
from damaris.experiments import Experiment
@@ -36,6 +37,19 @@ class _SandboxStdout:
return False
@contextlib.contextmanager
def _sandbox_stdout_redirect(log_callback):
"""Temporarily redirect process-global stdout/stderr to the sandbox log."""
old_stdout, old_stderr = sys.stdout, sys.stderr
sandbox = _SandboxStdout(log_callback)
try:
sys.stdout = sandbox
sys.stderr = sandbox
yield sandbox
finally:
sys.stdout, sys.stderr = old_stdout, old_stderr
class ExperimentHandling(threading.Thread):
"""
runs the experiment script in sandbox
@@ -52,17 +66,25 @@ class ExperimentHandling(threading.Thread):
self.data["__recentexperiment"]=-1
def synchronize(self, before=0, waitsteps=0.1):
while (self.data["__recentexperiment"]>self.data["__recentresult"]+before) and not self.quit_flag.isSet():
while (self.data["__recentexperiment"]>self.data["__recentresult"]+before) and not self.quit_flag.is_set():
self.quit_flag.wait(waitsteps)
if self.quit_flag.isSet():
if self.quit_flag.is_set():
raise StopExperiment
def sleep(self, seconds):
self.quit_flag.wait(seconds)
if self.quit_flag.isSet():
if self.quit_flag.is_set():
raise StopExperiment
def run(self):
# Redirect stdout/stderr so print() in sandboxed scripts goes to the GUI
if self._log_callback is not None:
with _sandbox_stdout_redirect(self._log_callback):
self._run_script()
else:
self._run_script()
def _run_script(self):
dataspace={}
exp_classes = __import__('damaris.experiments', dataspace, dataspace, ['Experiment'])
for name in dir(exp_classes):
@@ -77,13 +99,6 @@ class ExperimentHandling(threading.Thread):
self.location = None
exp_iterator=None
# Redirect stdout/stderr so print() in sandboxed scripts goes to the GUI
_orig_stdout = sys.stdout
_orig_stderr = sys.stderr
if self._log_callback is not None:
sys.stdout = _SandboxStdout(self._log_callback)
sys.stderr = _SandboxStdout(self._log_callback)
# check for time.sleep()
try:
tree = ast.parse(self.script)
@@ -131,7 +146,7 @@ class ExperimentHandling(threading.Thread):
traceback_file=None
return
while exp_iterator is not None and not self.quit_flag.isSet():
while exp_iterator is not None and not self.quit_flag.is_set():
# get next experiment from script
try:
job=next(exp_iterator)
@@ -171,7 +186,7 @@ class ExperimentHandling(threading.Thread):
# relax for a short time
if "__resultsinadvance" in self.data and self.data["__resultsinadvance"]+100<job.job_id:
self.quit_flag.wait(0.05)
if self.quit_flag.isSet():
if self.quit_flag.is_set():
dataspace=None
exp_iterator=None
break
@@ -181,7 +196,3 @@ class ExperimentHandling(threading.Thread):
dataspace=None
self.exp_iterator=None
self.writer=None
# Restore stdout/stderr
sys.stdout = _orig_stdout
sys.stderr = _orig_stderr