Skip to content

Commit b7081f5

Browse files
committed
fix(logging): tolerate unset options dict in worker bootstrap
CLI parsers seed salt._logging's global options dict at startup via LogLevelMixIn.__setup_logging_config(). Non-CLI consumers (RunnerClient.asynchronous, SSHClient, salt.utils.process.Process subclasses, parallel states) have no parser, so the dict stays None. Process.__new__ snapshots that None into instance.__logging_config__; wrapped_run_func then calls set_logging_options_dict(None) defensively, which forwards to set_lowest_log_level_by_opts(None).get(...) and AttributeErrors on the worker. The parent exits 0 with a misleading "Target did not return any data" / dead jid / 'result': None. Make set_logging_options_dict(None) and setup_logging() (when nothing has been seeded) no-op gracefully. Workers fall back to whatever logger configuration they inherited from the parent. CLI tools always seed before calling and are unaffected. Fixes #68332 Signed-off-by: Teddy Andrieux <teddy.andrieux@scality.com>
1 parent 86fc641 commit b7081f5

4 files changed

Lines changed: 36 additions & 1 deletion

File tree

changelog/68332.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed worker process crash when salt is used outside CLI tools.

salt/_logging/impl.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ def set_logging_options_dict(opts):
434434
"""
435435
Create a logging related options dictionary based off of the loaded salt config
436436
"""
437+
if opts is None:
438+
return
437439
try:
438440
if isinstance(set_logging_options_dict.__options_dict__, ImmutableDict):
439441
raise RuntimeError(
@@ -969,7 +971,7 @@ def setup_log_granular_levels(log_granular_levels):
969971
def setup_logging():
970972
opts = get_logging_options_dict()
971973
if not opts:
972-
raise RuntimeError("The logging options have not been set yet.")
974+
return
973975
if (
974976
opts.get("configure_console_logger", True)
975977
and not is_console_handler_configured()

tests/pytests/functional/utils/test_process.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,18 @@ def test_process_preimports_multiprocessing_connection_68573(tmp_path):
125125
cwd=str(tmp_path),
126126
)
127127
assert result.returncode == 0, f"stdout={result.stdout!r} stderr={result.stderr!r}"
128+
129+
130+
def test_process_unseeded_logging_options():
131+
"""
132+
Regression test for issue #68332.
133+
"""
134+
135+
def target():
136+
pass
137+
138+
salt._logging.set_logging_options_dict.__options_dict__ = None
139+
proc = salt.utils.process.Process(target=target)
140+
proc.start()
141+
proc.join()
142+
assert proc.exitcode == 0

tests/pytests/unit/_logging/test_impl.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
SaltLogRecord,
1414
get_log_record_factory,
1515
set_log_record_factory,
16+
set_logging_options_dict,
17+
setup_logging,
1618
)
1719

1820

@@ -119,3 +121,18 @@ def test_deferred_records_flushed_through_color_formatter(
119121
output = console_stream.getvalue()
120122
assert "buffered message" in output
121123
assert "DEBUG" in output
124+
125+
126+
def test_set_logging_options_dict_with_none():
127+
"""
128+
Regression test for issue #68332.
129+
"""
130+
set_logging_options_dict(None)
131+
132+
133+
def test_setup_logging_with_unseeded_options():
134+
"""
135+
Regression test for issue #68332.
136+
"""
137+
set_logging_options_dict.__options_dict__ = None
138+
setup_logging()

0 commit comments

Comments
 (0)