@@ -110,18 +110,22 @@ class ExceptionSink:
110
110
# Where to log stacktraces to in a SIGUSR2 handler.
111
111
_interactive_output_stream = None
112
112
113
- # An instance of `SignalHandler` which is invoked to handle a static set of specific
114
- # nonfatal signals (these signal handlers are allowed to make pants exit, but unlike SIGSEGV they
115
- # don't need to exit immediately).
113
+ # An instance of `SignalHandler` which is invoked to handle a static set of specific nonfatal
114
+ # signals (these signal handlers are allowed to make pants exit, but unlike SIGSEGV they don't
115
+ # need to exit immediately).
116
116
_signal_handler : SignalHandler = SignalHandler (pantsd_instance = False )
117
117
118
118
# These persistent open file descriptors are kept so the signal handler can do almost no work
119
119
# (and lets faulthandler figure out signal safety).
120
120
_pid_specific_error_fileobj = None
121
121
_shared_error_fileobj = None
122
122
123
+ # Set in methods on SignalHandler and exposed to the engine rust code.
123
124
_signal_sent : Optional [int ] = None
124
125
126
+ # Whether the rust logger has been initialized so we can stop doing extra work in this class.
127
+ _logging_initialized : bool = False
128
+
125
129
def __new__ (cls , * args , ** kwargs ):
126
130
raise TypeError ("Instances of {} are not allowed to be constructed!" .format (cls .__name__ ))
127
131
@@ -188,6 +192,16 @@ def reset_log_location(cls, new_log_location: str) -> None:
188
192
cls ._pid_specific_error_fileobj = pid_specific_error_stream
189
193
cls ._shared_error_fileobj = shared_error_stream
190
194
195
+ @classmethod
196
+ def set_logging_initialized (cls ):
197
+ """Set the flag (to True) which indicates that the rust logger has been initialized.
198
+
199
+ Class state:
200
+ - Overwrites `cls._logging_initialized`.
201
+ """
202
+ # NB: mutate the class variables!
203
+ cls ._logging_initialized = True
204
+
191
205
@classmethod
192
206
def exceptions_log_path (cls , for_pid = None , in_dir = None ):
193
207
"""Get the path to either the shared or pid-specific fatal errors log file."""
@@ -360,7 +374,8 @@ def log_exception(cls, exc_class=None, exc=None, tb=None, add_newline=False):
360
374
361
375
extra_err_msg = None
362
376
try :
363
- # Always output the unhandled exception details into a log file, including the traceback.
377
+ # Always output the unhandled exception details into a log file, including the
378
+ # traceback.
364
379
exception_log_entry = cls ._format_unhandled_exception_log (
365
380
exc , tb , add_newline , should_print_backtrace = True
366
381
)
@@ -369,8 +384,15 @@ def log_exception(cls, exc_class=None, exc=None, tb=None, add_newline=False):
369
384
extra_err_msg = "Additional error logging unhandled exception {}: {}" .format (exc , e )
370
385
logger .error (extra_err_msg )
371
386
372
- # Generate an unhandled exception report fit to be printed to the terminal.
373
- logger .exception (exc )
387
+ # The rust logger implementation is used for most of pants's execution, but at import time,
388
+ # we want to be able to see any stacktrace to know where the error is being raised.
389
+ if cls ._logging_initialized :
390
+ logger .exception (exc )
391
+ else :
392
+ exception_log_entry = cls ._format_unhandled_exception_log (
393
+ exc , tb , add_newline , should_print_backtrace = True
394
+ )
395
+ logger .error (exception_log_entry )
374
396
375
397
@classmethod
376
398
def _handle_signal_gracefully (cls , signum , signame , traceback_lines ):
0 commit comments