diff --git a/HISTORY.md b/HISTORY.md index 583062a142..4d1c0cf535 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,14 @@ Release History =============== +3.12.1 (2025-01-03) +------------------- + +**Fixed** +- Certificate validation may end up in error in highly concurrent environment using the experimental freethreaded build. + This was due to a racing condition in our "verify" caching logic (e.g. avoid creating duplicate ssl_context where one is sufficient). + The GIL prevented this issue. + 3.12.0 (2025-01-01) ------------------- diff --git a/src/niquests/__version__.py b/src/niquests/__version__.py index 24d0084a0a..eedb41f38d 100644 --- a/src/niquests/__version__.py +++ b/src/niquests/__version__.py @@ -9,9 +9,9 @@ __url__: str = "https://niquests.readthedocs.io" __version__: str -__version__ = "3.12.0" +__version__ = "3.12.1" -__build__: int = 0x031200 +__build__: int = 0x031201 __author__: str = "Kenneth Reitz" __author_email__: str = "me@kennethreitz.org" __license__: str = "Apache-2.0" diff --git a/src/niquests/adapters.py b/src/niquests/adapters.py index 711d071cbb..127797a134 100644 --- a/src/niquests/adapters.py +++ b/src/niquests/adapters.py @@ -565,13 +565,9 @@ def cert_verify( return need_reboot_conn: bool = False - verify_witness_bit: bool = ( - hasattr(conn, "_niquests_verify") and conn._niquests_verify == verify - ) + verify_witness_bit: bool = getattr(conn, "_niquests_verify", object()) == verify if not verify_witness_bit: - setattr(conn, "_niquests_verify", verify) - if verify: cert_loc: str | None = None cert_data: str | None = wassima.generate_ca_bundle() @@ -638,6 +634,7 @@ def cert_verify( conn.ca_cert_dir = None conn.ca_cert_data = None + setattr(conn, "_niquests_verify", verify) if cert: if not isinstance(cert, str): if "-----BEGIN CERTIFICATE-----" in cert[0]: @@ -1665,13 +1662,9 @@ def cert_verify( return False need_reboot_conn: bool = False - verify_witness_bit: bool = ( - hasattr(conn, "_niquests_verify") and conn._niquests_verify == verify - ) + verify_witness_bit: bool = getattr(conn, "_niquests_verify", object()) == verify if not verify_witness_bit: - setattr(conn, "_niquests_verify", verify) - if verify: cert_loc: str | None = None cert_data: str | None = wassima.generate_ca_bundle() @@ -1737,6 +1730,8 @@ def cert_verify( conn.ca_cert_dir = None conn.ca_cert_data = None + setattr(conn, "_niquests_verify", verify) + if cert: if not isinstance(cert, str): if "-----BEGIN CERTIFICATE-----" in cert[0]: diff --git a/src/niquests/help.py b/src/niquests/help.py index a262d2d823..75af6af029 100644 --- a/src/niquests/help.py +++ b/src/niquests/help.py @@ -58,6 +58,11 @@ wsproto = None # type: ignore +_IS_GIL_DISABLED: bool = ( + hasattr(sys, "_is_gil_enabled") and sys._is_gil_enabled() is False +) + + def _implementation(): """Return a dict with the Python implementation and version. @@ -132,6 +137,7 @@ def info(): "platform": platform_info, "implementation": implementation_info, "system_ssl": system_ssl_info, + "gil": not _IS_GIL_DISABLED, "urllib3.future": urllib3_info, "charset_normalizer": charset_normalizer_info, "idna": idna_info, @@ -209,8 +215,8 @@ def main() -> None: if __legacy_urllib3_version__ is not None: warnings.warn( - "urllib3-future is installed alongside (legacy) urllib3. This may cause compatibility issues." - "Some (Requests) 3rd parties may be bound to urllib3, therefor the plugins may wrongfully invoke" + "urllib3-future is installed alongside (legacy) urllib3. This may cause compatibility issues. " + "Some (Requests) 3rd parties may be bound to urllib3, therefor the plugins may wrongfully invoke " "urllib3 (legacy) instead of urllib3-future. To remediate this, run " "`python -m pip uninstall -y urllib3 urllib3-future`, then run `python -m pip install urllib3-future`.", UserWarning,