| from __future__ import annotations | |
| import atexit | |
| import faulthandler | |
| import os | |
| import platform | |
| import sys | |
| import threading | |
| import time | |
| import traceback | |
| from pathlib import Path | |
| _LOCK = threading.RLock() | |
| _STATE = { | |
| "installed": False, | |
| "log_file": None, | |
| "log_path": None, | |
| "stdout": None, | |
| "stderr": None, | |
| "prev_excepthook": None, | |
| "prev_threading_excepthook": None, | |
| "prev_unraisablehook": None, | |
| } | |
| class _TeeStream: | |
| def __init__(self, stream, log_file): | |
| self._stream = stream | |
| self._log_file = log_file | |
| def write(self, data): | |
| if not data: | |
| return 0 | |
| text = data.decode("utf-8", errors="replace") if isinstance(data, (bytes, bytearray)) else str(data) | |
| with _LOCK: | |
| written = _safe_write(self._stream, text) | |
| _safe_write(self._log_file, text) | |
| if "\n" in text or "\r" in text: | |
| _safe_flush(self._stream) | |
| _safe_flush(self._log_file) | |
| return written if written is not None else len(text) | |
| def flush(self): | |
| with _LOCK: | |
| _safe_flush(self._stream) | |
| _safe_flush(self._log_file) | |
| def isatty(self): | |
| return bool(getattr(self._stream, "isatty", lambda: False)()) | |
| def fileno(self): | |
| return getattr(self._stream, "fileno")() | |
| def writable(self): | |
| return bool(getattr(self._stream, "writable", lambda: True)()) | |
| def encoding(self): | |
| return getattr(self._stream, "encoding", "utf-8") | |
| def errors(self): | |
| return getattr(self._stream, "errors", "strict") | |
| def __getattr__(self, name): | |
| return getattr(self._stream, name) | |
| def _safe_write(stream, text): | |
| if stream is None: | |
| return None | |
| try: | |
| return stream.write(text) | |
| except Exception: | |
| return None | |
| def _safe_flush(stream): | |
| if stream is None: | |
| return | |
| try: | |
| stream.flush() | |
| except Exception: | |
| return | |
| def _flush_log(sync=False): | |
| log_file = _STATE.get("log_file") | |
| if log_file is None: | |
| return | |
| _safe_flush(log_file) | |
| if sync: | |
| try: | |
| os.fsync(log_file.fileno()) | |
| except Exception: | |
| return | |
| def _timestamp(): | |
| return time.strftime("%Y-%m-%d %H:%M:%S") | |
| def _log_line(message, sync=False): | |
| log_file = _STATE.get("log_file") | |
| if log_file is None: | |
| return | |
| with _LOCK: | |
| _safe_write(log_file, f"[crash-diagnostics {_timestamp()}] {message}\n") | |
| _flush_log(sync=sync) | |
| def _log_trace(prefix, exc_type, exc_value, exc_traceback): | |
| _log_line(prefix, sync=True) | |
| formatted = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback)).rstrip() | |
| if formatted: | |
| with _LOCK: | |
| _safe_write(_STATE.get("log_file"), f"{formatted}\n") | |
| _flush_log(sync=True) | |
| def _install_stream_tees(log_file): | |
| if _STATE["stdout"] is None: | |
| _STATE["stdout"] = sys.stdout | |
| if _STATE["stderr"] is None: | |
| _STATE["stderr"] = sys.stderr | |
| if sys.stdout is _STATE["stdout"]: | |
| sys.stdout = _TeeStream(sys.stdout, log_file) | |
| if sys.stderr is _STATE["stderr"]: | |
| sys.stderr = _TeeStream(sys.stderr, log_file) | |
| def _install_exception_hooks(): | |
| prev_excepthook = sys.excepthook | |
| _STATE["prev_excepthook"] = prev_excepthook | |
| def _excepthook(exc_type, exc_value, exc_traceback): | |
| _log_trace(f"Unhandled exception in main thread '{threading.current_thread().name}'", exc_type, exc_value, exc_traceback) | |
| if prev_excepthook not in (None, _excepthook): | |
| try: | |
| prev_excepthook(exc_type, exc_value, exc_traceback) | |
| return | |
| except Exception: | |
| pass | |
| sys.__excepthook__(exc_type, exc_value, exc_traceback) | |
| sys.excepthook = _excepthook | |
| if hasattr(threading, "excepthook"): | |
| prev_threading_excepthook = threading.excepthook | |
| _STATE["prev_threading_excepthook"] = prev_threading_excepthook | |
| def _threading_excepthook(args): | |
| thread_name = getattr(args.thread, "name", "unknown") | |
| _log_trace(f"Unhandled exception in thread '{thread_name}'", args.exc_type, args.exc_value, args.exc_traceback) | |
| if prev_threading_excepthook not in (None, _threading_excepthook): | |
| try: | |
| prev_threading_excepthook(args) | |
| except Exception: | |
| return | |
| threading.excepthook = _threading_excepthook | |
| if hasattr(sys, "unraisablehook"): | |
| prev_unraisablehook = sys.unraisablehook | |
| _STATE["prev_unraisablehook"] = prev_unraisablehook | |
| def _unraisablehook(unraisable): | |
| obj_name = type(unraisable.object).__name__ if getattr(unraisable, "object", None) is not None else "None" | |
| err_msg = getattr(unraisable, "err_msg", None) or "Unraisable exception" | |
| _log_line(f"{err_msg} on object type '{obj_name}'", sync=True) | |
| _log_trace("Unraisable exception traceback", unraisable.exc_type, unraisable.exc_value, unraisable.exc_traceback) | |
| if prev_unraisablehook not in (None, _unraisablehook): | |
| try: | |
| prev_unraisablehook(unraisable) | |
| except Exception: | |
| return | |
| sys.unraisablehook = _unraisablehook | |
| def _install_faulthandler(log_file): | |
| try: | |
| faulthandler.enable(file=log_file, all_threads=True) | |
| _log_line("faulthandler enabled for fatal native crashes", sync=True) | |
| except Exception as exc: | |
| _log_line(f"Failed to enable faulthandler: {exc}", sync=True) | |
| def _log_startup_context(anchor_path): | |
| _log_line(f"Crash diagnostics active. Log file: {_STATE['log_path']}", sync=True) | |
| _log_line(f"PID={os.getpid()} PPID={os.getppid() if hasattr(os, 'getppid') else 'n/a'}", sync=True) | |
| _log_line(f"Python={sys.version.splitlines()[0]}", sync=True) | |
| _log_line(f"Platform={platform.platform()}", sync=True) | |
| _log_line(f"CWD={os.getcwd()}", sync=True) | |
| _log_line(f"Entry={anchor_path}", sync=True) | |
| _log_line(f"ARGV={sys.argv}", sync=True) | |
| def _on_exit(): | |
| _log_line("Process exit reached", sync=True) | |
| def install_wgp_crash_diagnostics(anchor_file): | |
| try: | |
| with _LOCK: | |
| if _STATE["installed"]: | |
| return str(_STATE["log_path"] or "") | |
| anchor_path = Path(anchor_file).resolve() | |
| log_dir = anchor_path.parent / "crash" | |
| log_dir.mkdir(parents=True, exist_ok=True) | |
| log_path = log_dir / f"wgp_crash_{time.strftime('%Y%m%d_%H%M%S')}_pid{os.getpid()}.log" | |
| log_file = log_path.open("a", encoding="utf-8", buffering=1) | |
| _STATE["log_file"] = log_file | |
| _STATE["log_path"] = log_path | |
| _install_stream_tees(log_file) | |
| _install_exception_hooks() | |
| _install_faulthandler(log_file) | |
| atexit.register(_on_exit) | |
| _STATE["installed"] = True | |
| _log_startup_context(anchor_path) | |
| print(f"[crash-diagnostics] Logging to {log_path}") | |
| return str(log_path) | |
| except Exception: | |
| return "" | |
Xet Storage Details
- Size:
- 7.18 kB
- Xet hash:
- 8d48694016f9a72675a225f3fdcc38a9ed86a9e6f99e3d7fd2fbdcb503f89eea
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.