diff --git a/src/scancode/cli.py b/src/scancode/cli.py index 1376c6cfee..e48cb50276 100644 --- a/src/scancode/cli.py +++ b/src/scancode/cli.py @@ -1390,7 +1390,7 @@ def terminate_pool(pool): def terminate_pool_with_backoff(pool, number_of_trials=3): # try a few times to terminate, - for trial in range(number_of_trials, 1): + for trial in range(number_of_trials): try: pool.terminate() break diff --git a/tests/scancode/test_cli.py b/tests/scancode/test_cli.py index 858baf68ca..50bf5e504b 100644 --- a/tests/scancode/test_cli.py +++ b/tests/scancode/test_cli.py @@ -1036,3 +1036,48 @@ def test_scan_does_validate_input_and_fails_on_faulty_json_input(test_file, expe def test_scan_does_validate_input_and_does_not_fail_on_valid_json_input(): test_file = test_env.get_test_loc('various-inputs/true-scan-json.json') run_scan_click(['--from-json', test_file, '--json-pp', '-'], retry=False) + + +def test_terminate_pool_with_backoff_retries_on_windows_error(): + """ + Regression test: ensure terminate_pool_with_backoff actually executes + its retry loop. The old range(number_of_trials, 1) was always empty + so pool.terminate() was never called. + """ + import builtins + from unittest.mock import MagicMock + import scancode.cli as _cli_mod + from scancode.cli import terminate_pool_with_backoff + + _WindowsError = _cli_mod.__dict__.get( + 'WindowsError', + getattr(builtins, 'WindowsError', Exception), + ) + + pool = MagicMock() + call_count = [0] + + def flaky_terminate(): + call_count[0] += 1 + if call_count[0] < 2: + raise _WindowsError("fake windows error") + + pool.terminate.side_effect = flaky_terminate + + terminate_pool_with_backoff(pool, number_of_trials=3) + + assert pool.terminate.call_count == 2 + + +def test_terminate_pool_with_backoff_succeeds_on_first_try(): + """ + Ensure terminate_pool_with_backoff breaks out of loop immediately + on success without unnecessary retries. + """ + from unittest.mock import MagicMock + from scancode.cli import terminate_pool_with_backoff + + pool = MagicMock() + terminate_pool_with_backoff(pool, number_of_trials=3) + + assert pool.terminate.call_count == 1 \ No newline at end of file