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:
+46
-7
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user