fix(secrets): replace SIGALRM with cross-platform timeout (closes #91)#92
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Problem
codelens secretscrashed on Windows becausescripts/secrets_engine.pyusedsignal.signal(signal.SIGALRM, ...)to enforce a per-file regex timeout.SIGALRMis a POSIX-only signal — it does not exist on Windows — so every invocation raised:The surrounding
except (OSError, ValueError)fallback did not catchAttributeError, so the error propagated and killed the command. AllTestSecretsEnginetests failed on Windows for the same reason.Closes #91.
Approach
Chosen: Replace
SIGALRMentirely with aconcurrent.futures.ThreadPoolExecutor+future.result(timeout=...)based timeout. This was preferred over ahasattr(signal, "SIGALRM")guard because:except (OSError, ValueError)fallback (which only existed to paper over the Windows crash) is removed, along with the_regex_timeout_handlersignal handler.hasattrguard would have left Windows without any timeout, merely avoiding the crash).PER_FILE_REGEX_TIMEOUT(5s) and the file is still skipped on timeout via the existing_RegexTimeoutexception.Files changed
scripts/secrets_engine.py:import signalreplaced withimport concurrent.futures._regex_timeout_handler(signum, frame)(dead code after refactor)._ENTROPY_EXTENSIONS(single source of truth for the entropy-eligible extensions set, previously duplicated across two call sites)._scan_file_with_timeout(content, rel_path, ext, is_test)helper that runs_scan_file_patterns(+ optional_scan_file_entropy) inside a worker thread with a hard timeout.try/exceptSIGALRM block (and itsexcept (OSError, ValueError)fallback) indetect_secretswith a single call to_scan_file_with_timeout. Theexcept _RegexTimeout:handler is kept so timeout skips are still counted and logged.Verification
python scripts/codelens.py secretsno longer raisesAttributeErroron Windowssignalto deleteSIGALRM/alarm) —detect_secrets()runs cleanly and returns findings.TestSecretsEnginepassesPYTHONUTF8=1 python -m pytest tests/ --ignore=tests/test_integration.pyresults in 863 passed, 12 skipped, 0 failed.Notes
ThreadPoolExecutoris a daemon on Python 3.9+, so a runaway regex that exceeds the timeout does not block process exit on modern Python. On Python 3.8 (the project's minimum), the leaked worker self-terminates when the regex eventually completes; this matches the prior worst-case behaviour ofSIGALRM(which also could not actually interrupt a C-level regex match, only raise between bytecode instructions).secrets_enginechanged.detect_secrets()signature and return shape are identical.