Debugging: Erweiterte Debug-Ausgaben und Log-Verzeichnis-Verschiebung

Saxon Worker Pool Verbesserungen:
- Fügt umfangreiche DEBUG-Ausgaben in Java-Worker hinzu (Job-Parsing, Saxon-Ausführung)
- Fügt explizite flush()-Aufrufe hinzu um Buffering-Probleme zu vermeiden
- Zeigt Stack Traces bei Exceptions an
- Verbessert Exception-Handling (null-sichere getMessage())
- Verschiebt Worker-stderr-Logs von /tmp in Projektverzeichnis unter temp/
- Erweitert SaxonWorkerPool.__init__ um optionalen log_dir Parameter

Dies hilft, den genauen Crash-Punkt der Worker zu identifizieren.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 15:37:54 +01:00
parent ac654a6f7c
commit 8b29214abd
2 changed files with 48 additions and 7 deletions
+46 -7
View File
@@ -27,19 +27,30 @@ public class SaxonWorker {
String line;
System.err.println("SaxonWorker started and ready");
System.err.flush();
try {
while ((line = reader.readLine()) != null) {
System.err.println("DEBUG: Received line: " + line.substring(0, Math.min(100, line.length())));
System.err.flush();
if ("EXIT".equals(line.trim())) {
System.err.println("SaxonWorker exiting");
break;
}
try {
// Parse JSON job
// Parse job
System.err.println("DEBUG: Parsing job...");
System.err.flush();
String[] parts = line.split("\\t");
System.err.println("DEBUG: Parts count: " + parts.length);
System.err.flush();
if (parts.length < 3) {
System.out.println("ERROR: Invalid job format");
System.out.flush();
continue;
}
@@ -47,6 +58,9 @@ public class SaxonWorker {
String xslStylesheet = parts[1];
String outputFo = parts[2];
System.err.println("DEBUG: Building Saxon args...");
System.err.flush();
// Build Saxon arguments
List<String> saxonArgs = new ArrayList<>();
saxonArgs.add("-s:" + sourceXml);
@@ -63,6 +77,9 @@ public class SaxonWorker {
}
}
System.err.println("DEBUG: Running Saxon transformation...");
System.err.flush();
// Redirect Saxon output to stderr to avoid polluting stdout
PrintStream oldOut = System.out;
PrintStream oldErr = System.err;
@@ -80,21 +97,34 @@ public class SaxonWorker {
System.setOut(oldOut);
System.setErr(oldErr);
oldErr.println("DEBUG: Saxon transformation completed");
oldErr.flush();
// Send success response
System.out.println("OK");
System.out.flush();
} catch (Exception e) {
System.setOut(oldOut);
System.setErr(oldErr);
System.out.println("ERROR: " + e.getMessage());
oldErr.println("DEBUG: Saxon exception: " + e.getClass().getName());
oldErr.flush();
e.printStackTrace(oldErr);
System.out.println("ERROR: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getName()));
System.out.flush();
}
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
System.err.println("DEBUG: Job processing exception: " + e.getClass().getName());
System.err.flush();
e.printStackTrace(System.err);
System.out.println("ERROR: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getName()));
System.out.flush();
}
}
} catch (IOException e) {
System.err.println("SaxonWorker error: " + e.getMessage());
System.err.println("SaxonWorker I/O error: " + e.getMessage());
e.printStackTrace(System.err);
}
}
}
@@ -114,6 +144,7 @@ class SaxonWorkerPool:
java_vm_path: Path,
saxon_jar_path: Path,
classpath_cache: dict[Path, str],
log_dir: Optional[Path] = None,
):
"""
Initialisiert den Saxon-Worker-Pool.
@@ -123,11 +154,13 @@ class SaxonWorkerPool:
java_vm_path: Pfad zur Java VM Binary
saxon_jar_path: Pfad zur Saxon JAR-Datei
classpath_cache: Cache für Saxon-Classpaths
log_dir: Optionales Verzeichnis für Worker-Logs (Standard: temp_dir/temp)
"""
self.num_workers = num_workers
self.java_vm_path = java_vm_path
self.saxon_jar_path = saxon_jar_path
self.classpath_cache = classpath_cache
self.log_dir = log_dir
# Worker-Prozesse und Queues
self.workers: list[subprocess.Popen] = []
@@ -138,6 +171,7 @@ class SaxonWorkerPool:
# Temporäres Verzeichnis für kompilierte Java-Klasse
self.temp_dir: Optional[Path] = None
self.worker_class_path: Optional[Path] = None
self.worker_log_dir: Optional[Path] = None
# Initialisierung
self._compile_worker_class()
@@ -202,13 +236,18 @@ class SaxonWorkerPool:
classpath_separator = ";" if sys.platform == "win32" else ":"
full_classpath = str(self.worker_class_path) + classpath_separator + classpath
# Bestimme Log-Verzeichnis
self.worker_log_dir = self.log_dir if self.log_dir else self.temp_dir
if self.log_dir:
self.worker_log_dir.mkdir(parents=True, exist_ok=True)
for i in range(self.num_workers):
try:
# Starte JVM-Prozess mit SaxonWorker
cmd = [str(self.java_vm_path), "-cp", full_classpath, "SaxonWorker"]
# Öffne stderr-Log-Datei für diesen Worker
stderr_log = self.temp_dir / f"worker_{i}_stderr.log"
stderr_log = self.worker_log_dir / f"worker_{i}_stderr.log"
stderr_file = open(stderr_log, "w", encoding="utf-8")
process = subprocess.Popen(
@@ -281,7 +320,7 @@ class SaxonWorkerPool:
# Prüfe ob Worker noch läuft
if worker.poll() is not None:
# Worker ist tot!
stderr_log = self.temp_dir / f"worker_{worker_idx}_stderr.log"
stderr_log = self.worker_log_dir / f"worker_{worker_idx}_stderr.log"
try:
with open(stderr_log, "r") as f:
stderr_content = f.read()
@@ -318,7 +357,7 @@ class SaxonWorkerPool:
else:
# Leere Antwort bedeutet Worker ist crashed
if not response:
stderr_log = self.temp_dir / f"worker_{worker_idx}_stderr.log"
stderr_log = self.worker_log_dir / f"worker_{worker_idx}_stderr.log"
try:
with open(stderr_log, "r") as f:
stderr_content = f.read()[-500:] # Letzte 500 Zeichen
+2
View File
@@ -758,11 +758,13 @@ class MainWindow(QMainWindow):
# Erstelle Worker-Pool
num_workers = app_settings.max_workers
log_dir = self.project.project_dir / "temp"
pool = SaxonWorkerPool(
num_workers=num_workers,
java_vm_path=java_vm.path_to_binary_file,
saxon_jar_path=saxon_jar.path_to_jar_file,
classpath_cache=TransformationJob._classpath_cache,
log_dir=log_dir,
)
# Setze globalen Pool