Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions agent-notes/improve-crash-lifetime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Goal

Keep fatal traceback output attached to an open error-log stream through shutdown.

# State

Pass the existing error-handler stream directly to faulthandler. Remove the wrapper that only forwarded fileno. Package shutdown and an exit callback disable package-enabled fault handling before logging closes its files. This PR is independently based on integrated master and contains no UTF-8 PR commits.

# Decisions and why

faulthandler retains a file descriptor, not a logging handler. Its stream must stay open until fault handling is disabled. The exit callback runs before logging's earlier registered shutdown callback. Disabling is a no-op when this package has not enabled fault handling. Fatal dumps remain raw output rather than formatted log records.

# Surprises

The removed StreamToLogger never redirected log writes; its description was misleading.

# Next step

Read this PR's existing package checks. Subsequent setup/reconfiguration changes must retain the same file-lifetime ordering. No merge or release.
27 changes: 14 additions & 13 deletions logger_setup/crashlogger.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import logging
import atexit
import faulthandler

CRASHLOGGER_NAME = "APPCRASH"
_enabled = False


class StreamToLogger(object):
"""
Fake file-like stream object that redirects writes to a logger instance.
"""
def enable_crashlogger(error_handler):
global _enabled
faulthandler.enable(error_handler.stream)
_enabled = True

def __init__(self, handler):
self.handler = handler

def fileno(self):
return self.handler.stream.fileno()
def disable_crashlogger():
global _enabled
if _enabled:
faulthandler.disable()
_enabled = False


def enable_crashlogger(error_handler):
stream = StreamToLogger(error_handler)
faulthandler.enable(stream)
# logging registers its shutdown before importing this module. Exit callbacks
# run in reverse order, so release the fault descriptor before logs are closed.
atexit.register(disable_crashlogger)
1 change: 1 addition & 0 deletions logger_setup/logger_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ def setup_logging(


def shutdown():
crashlogger.disable_crashlogger()
logging.shutdown()
Loading