GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-149816: Fix SNI callback callable race by kiri11 · Pull Request #150018 · python/cpython

Conversation

@kiri11

@kiri11 kiri11 commented May 18, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Problem

Fix a use-after-free race in the SSL SNI callback on free-threaded builds. When sni_callback is replaced or cleared on one thread while another thread is mid-handshake, the old callback object could be freed before the handshake thread finishes calling it.

  • Reader side (_servername_callback): acquire sslctx's critical section, snapshot the callback with Py_XNewRef into a local, then release. The local strong reference keeps the callable alive for the duration of the call.
  • Setter side (sni_callback_set): already holds the same critical section via @critical_section clinic annotation. Uses Py_XSETREF to swap the pointer and decref the old callback atomically. The OpenSSL callback registration is set after the pointer is stored, so a concurrent handshake always finds a valid callable.
  • Setter clearing (sni_callback = None): unregisters the OpenSSL callback first, then clears the Python reference. Serialized against the reader by the same critical section.

Testing

Adds a free-threading stress test that spawns handshake workers and a callback-toggling thread concurrently.

Plus manually tested on MacOS.

Before

% ./python.exe -m test test_ssl -m test_sni_callback_race
Raised RLIMIT_NOFILE: 256 -> 1024
Using random seed: 2655205590
0:00:00 load avg: 4.31 Run 1 test sequentially in a single process
0:00:00 load avg: 4.31 [1/1] test_ssl
==================
WARNING: ThreadSanitizer: data race (pid=68672)
  Write of size 8 at 0x000126f10588 by thread T29:
    #0 _ssl__SSLContext_sni_callback_set_impl _ssl.c:5304 (_ssl.cpython-316t-darwin.so:arm64+0xe5f0)
    #1 _ssl__SSLContext_sni_callback_set _ssl.c.h:2266 (_ssl.cpython-316t-darwin.so:arm64+0xe5f0)
    #2 _PyObject_GenericSetAttrWithDict object.c:2049 (python.exe:arm64+0x1000dd900)
    #3 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10026e378)

  Previous read of size 8 at 0x000126f10588 by thread T13:
    #0 _servername_callback _ssl.c:5159 (_ssl.cpython-316t-darwin.so:arm64+0xffa0)
    #1 final_server_name <null> (libssl.3.dylib:arm64+0x5c31c)
    #2 _PyEval_EvalFrameDefault generated_cases.c.h:4142 (python.exe:arm64+0x1001c5b50)
    #3 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10026e378)

  Thread T29 (tid=707684, running) created by main thread at:
    #0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x31d84)
    #1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10026d9f8)
    #2 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x10032782c)
    #3 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100326894)
    #4 cfunction_call methodobject.c:564 (python.exe:arm64+0x1000d27b4)

  Thread T13 (tid=707668, running) created by main thread at:
    #0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x31d84)
    #1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10026d9f8)
    #2 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x10032782c)
    #3 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100326894)
    #4 cfunction_call methodobject.c:564 (python.exe:arm64+0x1000d27b4)

SUMMARY: ThreadSanitizer: data race _ssl.c:5304 in _ssl__SSLContext_sni_callback_set_impl
==================
Warning -- Unraisable exception
Exception ignored in ssl servername callback while calling set SNI callback <NULL>:
Traceback (most recent call last):
  File "/Users/kignatev/PycharmProjects/cpython/Lib/ssl.py", line 963, in do_handshake
    self._sslobj.do_handshake()
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^
SystemError: null argument to internal routine
Fatal Python error: Segmentation fault

<Cannot show all threads while the GIL is disabled>
Stack (most recent call first):
  <invalid frame>

Current thread's C stack trace (most recent call first):
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _Py_DumpStack+0x44 [0x104db912c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at faulthandler_fatal_error+0x330 [0x104dddf98]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN6__tsanL21CallUserSignalHandlerEPNS_11ThreadStateEbbiPN11__sanitizer23__sanitizer_siginfo_padEPv+0x104 [0x10570f910]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _Z10sighandleriPN11__sanitizer23__sanitizer_siginfo_padEPv+0x1a8 [0x10570fb68]
  Binary file "/usr/lib/system/libsystem_platform.dylib", at _sigtramp+0x38 [0x182e257a4]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0xc71c [0x104d152e4]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at object_vacall+0x138 [0x104babb78]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at PyObject_CallFunctionObjArgs+0x38 [0x104babce0]
  Binary file "/Users/kignatev/PycharmProjects/cpython/Modules/_ssl.cpython-316t-darwin.so", at _servername_callback+0x274 [0x10f9c01c8]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at final_server_name+0x6c [0x113db4320]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at tls_parse_all_extensions+0xa8 [0x113db3a10]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at tls_post_process_client_hello+0x560 [0x113dcf678]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at state_machine+0x59c [0x113dbe824]
  Binary file "/Users/kignatev/PycharmProjects/cpython/Modules/_ssl.cpython-316t-darwin.so", at _ssl__SSLSocket_do_handshake+0x184 [0x10f9c093c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0x4f8c [0x104d0db54]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyObject_VectorcallPrepend+0x144 [0x104bab0c8]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at context_run+0x88 [0x104d3b77c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at PyObject_Vectorcall+0x58 [0x104ba9a40]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _Py_VectorCallInstrumentation_StackRefSteal+0x12c [0x104d07d10]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0x21b4 [0x104d0ad7c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyObject_VectorcallPrepend+0x144 [0x104bab0c8]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at thread_run+0xe0 [0x104e6ff58]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at pythread_wrapper+0x1c [0x104db637c]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at __tsan_thread_start_func+0x8c [0x105709cf8]
  Binary file "/usr/lib/system/libsystem_pthread.dylib", at _pthread_start+0x88 [0x182e1bc58]
  Binary file "/usr/lib/system/libsystem_pthread.dylib", at thread_start+0x8 [0x182e16c1c]
ThreadSanitizer:DEADLYSIGNAL
==68672==ERROR: ThreadSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000104d0ef10 bp 0x00017e422240 sp 0x00017e421fe0 T707674)
==68672==The signal is caused by a READ memory access.
==68672==Hint: address points to the zero page.
Warning -- Unraisable exception
Exception ignored in ssl servername callback while calling set SNI callback <NULL>:
Traceback (most recent call last):
  File "/Users/kignatev/PycharmProjects/cpython/Lib/ssl.py", line 963, in do_handshake
    self._sslobj.do_handshake()
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^
SystemError: null argument to internal routine
    #0 _PyEval_EvalFrameDefault generated_cases.c.h:5550 (python.exe:arm64+0x1001c6f10)
    #1 _PyEval_EvalFrame pycore_ceval.h:122 (python.exe:arm64+0x1001bf6e8)
    #2 _PyEval_Vector ceval.c:2156 (python.exe:arm64+0x1001bf6e8)
    #3 _PyObject_VectorcallTstate pycore_call.h:144 (python.exe:arm64+0x100063b74)
    #4 object_vacall call.c:823 (python.exe:arm64+0x100063b74)
    #5 PyObject_CallFunctionObjArgs call.c:977 (python.exe:arm64+0x100063cdc)
    #6 _servername_callback _ssl.c:5214 (_ssl.cpython-316t-darwin.so:arm64+0x101c4)
    #7 final_server_name <null> (libssl.3.dylib:arm64+0x5c31c)
    #8 tls_parse_all_extensions <null> (libssl.3.dylib:arm64+0x5ba0c)
    #9 tls_post_process_client_hello <null> (libssl.3.dylib:arm64+0x77674)
    #10 state_machine <null> (libssl.3.dylib:arm64+0x66820)
    #11 _ssl__SSLSocket_do_handshake_impl _ssl.c:1098 (_ssl.cpython-316t-darwin.so:arm64+0x10938)
    #12 _ssl__SSLSocket_do_handshake _ssl.c.h:30 (_ssl.cpython-316t-darwin.so:arm64+0x10938)
    #13 _PyEval_EvalFrameDefault generated_cases.c.h:4142 (python.exe:arm64+0x1001c5b50)
    #14 _PyEval_EvalFrame pycore_ceval.h:122 (python.exe:arm64+0x1001bf6e8)
    #15 _PyEval_Vector ceval.c:2156 (python.exe:arm64+0x1001bf6e8)
    #16 _PyObject_VectorcallTstate pycore_call.h:144 (python.exe:arm64+0x1000630c4)
    #17 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x1000630c4)
    #18 _PyObject_VectorcallTstate pycore_call.h:144 (python.exe:arm64+0x1001f3778)
    #19 context_run context.c:727 (python.exe:arm64+0x1001f3778)
    #20 _PyObject_VectorcallTstate pycore_call.h:144 (python.exe:arm64+0x100061a3c)
    #21 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100061a3c)
    #22 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:775 (python.exe:arm64+0x1001bfd0c)
    #23 _PyEval_EvalFrameDefault generated_cases.c.h:1846 (python.exe:arm64+0x1001c2d78)
    #24 _PyEval_EvalFrame pycore_ceval.h:122 (python.exe:arm64+0x1001bf6e8)
    #25 _PyEval_Vector ceval.c:2156 (python.exe:arm64+0x1001bf6e8)
    #26 _PyObject_VectorcallTstate pycore_call.h:144 (python.exe:arm64+0x1000630c4)
    #27 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x1000630c4)
    #28 thread_run _threadmodule.c:388 (python.exe:arm64+0x100327f54)
    #29 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10026e378)
    #30 __tsan_thread_start_func <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x31cf4)
    #31 _pthread_start <null> (libsystem_pthread.dylib:arm64e+0x6c54)
    #32 thread_start <null> (libsystem_pthread.dylib:arm64e+0x1c18)

==68672==Register values:
 x[0] = 0x000000010e21dc88   x[1] = 0x00000001171c02e8   x[2] = 0x0000000000000000   x[3] = 0x000000017e422250
 x[4] = 0x0000000000000003   x[5] = 0x0000000000000000   x[6] = 0x0000000000000000   x[7] = 0x0000000000366b00
 x[8] = 0x0000000000000030   x[9] = 0x00000001171c0338  x[10] = 0x0000000000000001  x[11] = 0x0000000000000003
x[12] = 0x000000010505bda1  x[13] = 0x0000000000000003  x[14] = 0x0000000000000075  x[15] = 0x00000001eec259a0
x[16] = 0x0000000000000018  x[17] = 0x000000010e21dc70  x[18] = 0x0000000000000000  x[19] = 0x00000001171c0328
x[20] = 0x00000001171c0358  x[21] = 0x0000000104fd7da8  x[22] = 0x000000030e1001c0  x[23] = 0x000000030e1001c0
x[24] = 0x0000000000000000  x[25] = 0x0000000000000001  x[26] = 0x000000000000001d  x[27] = 0x00000001171c02e8
x[28] = 0x00000001240b8000     fp = 0x000000017e422240     lr = 0x0000000104d152e4     sp = 0x000000017e421fe0
ThreadSanitizer can not provide additional info.
SUMMARY: ThreadSanitizer: SEGV generated_cases.c.h:5550 in _PyEval_EvalFrameDefault
==68672==ABORTING
Fatal Python error: Aborted

<Cannot show all threads while the GIL is disabled>
Stack (most recent call first):
  <invalid frame>

Current thread's C stack trace (most recent call first):
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _Py_DumpStack+0x44 [0x104db912c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at faulthandler_fatal_error+0x330 [0x104dddf98]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN6__tsanL21CallUserSignalHandlerEPNS_11ThreadStateEbbiPN11__sanitizer23__sanitizer_siginfo_padEPv+0x104 [0x10570f910]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _Z10sighandleriPN11__sanitizer23__sanitizer_siginfo_padEPv+0x1a8 [0x10570fb68]
  Binary file "/usr/lib/system/libsystem_platform.dylib", at _sigtramp+0x38 [0x182e257a4]
  Binary file "/usr/lib/system/libsystem_pthread.dylib", at pthread_kill+0x128 [0x182e1b8d8]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at wrap_pthread_kill+0x134 [0x105710278]
  Binary file "/usr/lib/system/libsystem_c.dylib", at abort+0x94 [0x182d22790]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN11__sanitizer6AtexitEPFvvE+0x0 [0x1056f11b4]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN11__sanitizer3DieEv+0x68 [0x1056f06e4]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN11__sanitizer13SignalContextC1EPvS1_+0x0 [0x1056fd974]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _ZN6__tsanL21CallUserSignalHandlerEPNS_11ThreadStateEbbiPN11__sanitizer23__sanitizer_siginfo_padEPv+0x104 [0x10570f910]
  Binary file "/opt/homebrew/Cellar/llvm/22.1.5/lib/clang/22/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib", at _Z10sighandleriPN11__sanitizer23__sanitizer_siginfo_padEPv+0x1a8 [0x10570fb68]
  Binary file "/usr/lib/system/libsystem_platform.dylib", at _sigtramp+0x38 [0x182e257a4]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0xc71c [0x104d152e4]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at object_vacall+0x138 [0x104babb78]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at PyObject_CallFunctionObjArgs+0x38 [0x104babce0]
  Binary file "/Users/kignatev/PycharmProjects/cpython/Modules/_ssl.cpython-316t-darwin.so", at _servername_callback+0x274 [0x10f9c01c8]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at final_server_name+0x6c [0x113db4320]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at tls_parse_all_extensions+0xa8 [0x113db3a10]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at tls_post_process_client_hello+0x560 [0x113dcf678]
  Binary file "/opt/homebrew/Cellar/openssl@3/3.6.2/lib/libssl.3.dylib", at state_machine+0x59c [0x113dbe824]
  Binary file "/Users/kignatev/PycharmProjects/cpython/Modules/_ssl.cpython-316t-darwin.so", at _ssl__SSLSocket_do_handshake+0x184 [0x10f9c093c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0x4f8c [0x104d0db54]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyObject_VectorcallPrepend+0x144 [0x104bab0c8]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at context_run+0x88 [0x104d3b77c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at PyObject_Vectorcall+0x58 [0x104ba9a40]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _Py_VectorCallInstrumentation_StackRefSteal+0x12c [0x104d07d10]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_EvalFrameDefault+0x21b4 [0x104d0ad7c]
  Binary file "/Users/kignatev/PycharmProjects/cpython/python.exe", at _PyEval_Vector+0x2d8 [0x104d076ec]
  <truncated rest of calls>
zsh: abort      ./python.exe -m test test_ssl -m test_sni_callback_race

After

0:00:00 load avg: 4.18 [1/1] test_ssl passed

Using Repro:

% ./python.exe cpython-ft/repros/49.py
finding: 49 SSLContext.sni_callback replacement race
expected signal: native crash/fatal error/sanitizer use-after-free during concurrent SNI handshakes
parameters: seconds=10; Python=3.16.0a0; GIL_enabled=False; workers=28
------------------------------------------------------------------------
Completed without interpreter crash: 53271 handshakes, 0 Python-level failures, 245825 toggles.

More info

  • Issue: 22 free-threading race conditions #149816

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@kiri11
Add test_sni_callback_race
89d0b19
@bedevere-app bedevere-app Bot added the tests Tests in the Lib/test dir label May 18, 2026
@python-cla-bot

python-cla-bot Bot commented May 18, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app

bedevere-app Bot commented May 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kiri11
Improve test_sni_callback_race
be11d8b
@bedevere-app

bedevere-app Bot commented May 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kiri11
Fix SNI callback callable race use-after-free
63d7bab
In Modules/_ssl.c
@bedevere-app

bedevere-app Bot commented May 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@kiri11 kiri11 changed the title Add test_sni_callback_race gh-149816: Fix SNI callback callable race May 18, 2026
@bedevere-app bedevere-app Bot mentioned this pull request May 18, 2026
22 free-threading race conditions #149816
Open
13 of 24 tasks
@kiri11
Merge branch 'main' into ssl-rc-ft-49
806f3f1
@bedevere-app

bedevere-app Bot commented May 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

blurb-it Bot and others added 6 commits May 18, 2026 22:45
@blurb-it
📜🤖 Added by blurb_it.
1920fcb
@kiri11
Reorder imports
fb02f9d
@kiri11
Py_XDECREF in error case
dd20d00
@kiri11
Remove callback before Py_CLEAR
1548b6e
@kiri11
Remove FT_ATOMIC_LOAD_PTR_RELAXED
67da443
@kiri11
Don't allow callback == NULL
1ecc7df
@kiri11
kiri11 marked this pull request as ready for review May 19, 2026 00:17
@kiri11
kiri11 requested review from gpshead and picnixz as code owners May 19, 2026 00:17
@bedevere-app bedevere-app Bot added the awaiting review label May 19, 2026
@cmaloney cmaloney added the sprint label May 19, 2026
@github-project-automation github-project-automation Bot added this to Sprint May 19, 2026
@github-project-automation github-project-automation Bot moved this to Todo in Sprint May 19, 2026
encukou
encukou reviewed May 19, 2026
View reviewed changes
Comment thread Modules/_ssl.c
Comment on lines +5310 to +5323
if (!PyCallable_Check(value)) {
SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL);
}
else {
if (!PyCallable_Check(value)) {
SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL);
PyErr_SetString(PyExc_TypeError,
"not a callable object");
Py_CLEAR(self->set_sni_cb);
if (value != Py_None) {
PyErr_SetString(PyExc_TypeError, "not a callable object");
return -1;
}
self->set_sni_cb = Py_NewRef(value);
SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback);
}
else {
Py_INCREF(value);
PyObject *old_cb = _Py_atomic_exchange_ptr(&self->set_sni_cb, value);
Py_XDECREF(old_cb);
SSL_CTX_set_tlsext_servername_arg(self->ctx, self);
SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback);

@encukou encukou May 19, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look unnecessary if set_sni_cb is always accessed in a critical section.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@kiri11 kiri11 May 19, 2026

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately just the critical section didn't help (thread sanitizer kept complaining). Probably because it's getting accessed from within ssl library itself, so we can't guard against that.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@kiri11 kiri11 May 19, 2026

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I think I got it working

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
kiri11 added 2 commits May 18, 2026 18:31
@kiri11
Simplify test
32e5ba4
@kiri11
Simplify exchange in critical section
e1f1f4a
@kiri11
kiri11 requested a review from encukou May 19, 2026 01:41
@encukou encukou added the needs backport to 3.13 only security fixes label May 19, 2026
@encukou encukou added needs backport to 3.14 bugs and security fixes needs backport to 3.15 bugs and security fixes labels May 19, 2026
@encukou
encukou merged commit 8b31d08 into python:main May 19, 2026
61 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@miss-islington-app

miss-islington-app Bot commented May 19, 2026

Copy link
Copy Markdown

Thanks @kiri11 for the PR, and @encukou for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14, 3.15.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting review label May 19, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in Sprint May 19, 2026
@miss-islington-app

miss-islington-app Bot commented May 19, 2026

Copy link
Copy Markdown

Sorry, @kiri11 and @encukou, I could not cleanly backport this to 3.13 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker 8b31d08e62b9714cf8dd1d8b19afa5ecbad2414a 3.13
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app

bedevere-app Bot commented May 19, 2026

Copy link
Copy Markdown

GH-150099 is a backport of this pull request to the 3.15 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@miss-islington-app miss-islington-app Bot assigned encukou May 19, 2026
@bedevere-app bedevere-app Bot removed the needs backport to 3.15 bugs and security fixes label May 19, 2026
@bedevere-app

bedevere-app Bot commented May 19, 2026

Copy link
Copy Markdown

GH-150100 is a backport of this pull request to the 3.14 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label May 19, 2026
@encukou encukou removed the needs backport to 3.13 only security fixes label May 19, 2026
encukou pushed a commit that referenced this pull request May 19, 2026
@miss-islington @kiri11
[3.14] gh-149816: Fix SNI callback callable race (GH-150018) (GH-150100)
2744371
(cherry picked from commit 8b31d08)

Co-authored-by: Kirill Ignatev <[email protected]>
@colesbury colesbury mentioned this pull request May 21, 2026
Data race in test_ssl.test_sni_callback_race #150191
Closed
serhiy-storchaka pushed a commit that referenced this pull request Jun 8, 2026
@miss-islington @kiri11 @encukou
[3.15] gh-149816: Fix SNI callback callable race (GH-150018) (GH-150099)
9997975
(cherry picked from commit 8b31d08)

Co-authored-by: Kirill Ignatev <[email protected]>
Co-authored-by: Petr Viktorin <[email protected]>
@kumaraditya303

kumaraditya303 commented Jul 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This PR does not fixes the internal data races in openssl, see #150191 (comment) for the details of the race.

For now I have skipped this test under TSAN to keep TSAN CI working but this needs to be either fixed properly or documented as not thread safe as most other ssl operations.

cc @encukou

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@gpshead gpshead Awaiting requested review from gpshead gpshead is a code owner
@picnixz picnixz Awaiting requested review from picnixz picnixz is a code owner
@encukou encukou Awaiting requested review from encukou

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@encukou encukou

Labels

sprint tests Tests in the Lib/test dir

Projects

Sprint
Archived in project

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@kiri11 @kumaraditya303 @encukou @cmaloney
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.