Bug report
Bug description:
Created from gh-153852 TSAN-0035
sock->sock_timeout is a plain PyTime_t and have no synchronization. On the free-threaded build, using the same socket from multiple threads causes a c-level data race , reported by TSAN.
Repro:
import socket
import threading
s = socket.socket()
barrier = threading.Barrier(2)
N = 1000
def reader():
barrier.wait()
for _ in range(N):
s.gettimeout()
def writer():
barrier.wait()
for _ in range(N):
s.settimeout(1.0)
threads = [threading.Thread(target=reader), threading.Thread(target=writer)]
for t in threads:
t.start()
for t in threads:
t.join()
s.close()
print("done")
Output:
python.exe(20351,0x204cf7840) malloc: nano zone abandoned due to inability to reserve vm space.
==================
WARNING: ThreadSanitizer: data race (pid=20351)
Read of size 8 at 0x00010e600198 by thread T1:
#0 sock_gettimeout_method socketmodule.c:3320 (_socket.cpython-316t-darwin.so:arm64+0x84b8)
#1 method_vectorcall_NOARGS descrobject.c:448 (python.exe:arm64+0x1000a0c94)
#2 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88)
#3 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68)
#4 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8)
#5 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c)
#6 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8)
#7 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984)
#8 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88)
#9 context_run context.c:731 (python.exe:arm64+0x1002dff38)
#10 method_vectorcall_FASTCALL_KEYWORDS descrobject.c:421 (python.exe:arm64+0x1000a0b7c)
#11 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88)
#12 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68)
#13 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8)
#14 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c)
#15 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8)
#16 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984)
#17 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88)
#18 _PyObject_Call call.c:348 (python.exe:arm64+0x100088e48)
#19 PyObject_Call call.c:373 (python.exe:arm64+0x100088ec0)
#20 thread_run _threadmodule.c:388 (python.exe:arm64+0x1004582e0)
#21 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10038fe08)
Previous write of size 8 at 0x00010e600198 by thread T2:
#0 sock_settimeout socketmodule.c:3264 (_socket.cpython-316t-darwin.so:arm64+0x83fc)
#1 method_vectorcall_O descrobject.c:476 (python.exe:arm64+0x1000a0e38)
#2 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88)
#3 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68)
#4 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8)
#5 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c)
#6 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8)
#7 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984)
#8 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88)
#9 context_run context.c:731 (python.exe:arm64+0x1002dff38)
#10 method_vectorcall_FASTCALL_KEYWORDS descrobject.c:421 (python.exe:arm64+0x1000a0b7c)
#11 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88)
#12 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68)
#13 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8)
#14 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c)
#15 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8)
#16 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984)
#17 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88)
#18 _PyObject_Call call.c:348 (python.exe:arm64+0x100088e48)
#19 PyObject_Call call.c:373 (python.exe:arm64+0x100088ec0)
#20 thread_run _threadmodule.c:388 (python.exe:arm64+0x1004582e0)
#21 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10038fe08)
Thread T1 (tid=28859963, running) created by main thread at:
#0 pthread_create <null>:126882288 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
#1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10038f000)
#2 PyThread_start_joinable_thread thread_pthread.h:323 (python.exe:arm64+0x10038ee38)
#3 ThreadHandle_start _threadmodule.c:475 (python.exe:arm64+0x10045809c)
#4 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x100457b7c)
#5 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100456ae0)
#6 cfunction_call methodobject.c:564 (python.exe:arm64+0x1001310f4)
#7 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x100087f70)
#8 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088c28)
#9 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68)
#10 _PyEval_EvalFrameDefault generated_cases.c.h:3474 (python.exe:arm64+0x100298e58)
#11 PyEval_EvalCode ceval.c:679 (python.exe:arm64+0x10028fb74)
#12 run_eval_code_obj pythonrun.c:1406 (python.exe:arm64+0x10036aea4)
#13 run_mod pythonrun.c:1509 (python.exe:arm64+0x10036abd4)
#14 _PyRun_SimpleFile pythonrun.c:544 (python.exe:arm64+0x100365d88)
#15 _PyRun_AnyFile pythonrun.c:92 (python.exe:arm64+0x100365534)
#16 Py_RunMain main.c:891 (python.exe:arm64+0x1003a7aec)
#17 pymain_main main.c:921 (python.exe:arm64+0x1003a7f3c)
#18 Py_BytesMain main.c:945 (python.exe:arm64+0x1003a8010)
#19 main python.c:15 (python.exe:arm64+0x1000032ac)
Thread T2 (tid=28859964, running) created by main thread at:
#0 pthread_create <null>:126884528 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
#1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10038f000)
#2 PyThread_start_joinable_thread thread_pthread.h:323 (python.exe:arm64+0x10038ee38)
#3 ThreadHandle_start _threadmodule.c:475 (python.exe:arm64+0x10045809c)
#4 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x100457b7c)
#5 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100456ae0)
#6 cfunction_call methodobject.c:564 (python.exe:arm64+0x1001310f4)
#7 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x100087f70)
#8 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088c28)
#9 _Py_VectorCall_StackRefSteal ceval.c:726 (python.exe:arm64+0x1002903e4)
#10 _PyEval_EvalFrameDefault generated_cases.c.h (python.exe:arm64+0x1002995c4)
#11 PyEval_EvalCode ceval.c:679 (python.exe:arm64+0x10028fb74)
#12 run_eval_code_obj pythonrun.c:1406 (python.exe:arm64+0x10036aea4)
#13 run_mod pythonrun.c:1509 (python.exe:arm64+0x10036abd4)
#14 _PyRun_SimpleFile pythonrun.c:544 (python.exe:arm64+0x100365d88)
#15 _PyRun_AnyFile pythonrun.c:92 (python.exe:arm64+0x100365534)
#16 Py_RunMain main.c:891 (python.exe:arm64+0x1003a7aec)
#17 pymain_main main.c:921 (python.exe:arm64+0x1003a7f3c)
#18 Py_BytesMain main.c:945 (python.exe:arm64+0x1003a8010)
#19 main python.c:15 (python.exe:arm64+0x1000032ac)
SUMMARY: ThreadSanitizer: data race socketmodule.c:3320 in sock_gettimeout_method
==================
done
ThreadSanitizer: reported 1 warnings
[1] 20351 abort ./python.exe repro_sock_timeout_race.py
Proposed fix:
Wrap s->sock_timeout with _Py_atomic_load_int64_relaxed
I have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
Reactions are currently unavailable
Bug report
Bug description:
Created from gh-153852 TSAN-0035
sock->sock_timeout is a plain PyTime_t and have no synchronization. On the free-threaded build, using the same socket from multiple threads causes a c-level data race , reported by TSAN.
Repro:
Output:
python.exe(20351,0x204cf7840) malloc: nano zone abandoned due to inability to reserve vm space. ================== WARNING: ThreadSanitizer: data race (pid=20351) Read of size 8 at 0x00010e600198 by thread T1: #0 sock_gettimeout_method socketmodule.c:3320 (_socket.cpython-316t-darwin.so:arm64+0x84b8) #1 method_vectorcall_NOARGS descrobject.c:448 (python.exe:arm64+0x1000a0c94) #2 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88) #3 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68) #4 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8) #5 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c) #6 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8) #7 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984) #8 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88) #9 context_run context.c:731 (python.exe:arm64+0x1002dff38) #10 method_vectorcall_FASTCALL_KEYWORDS descrobject.c:421 (python.exe:arm64+0x1000a0b7c) #11 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88) #12 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68) #13 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8) #14 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c) #15 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8) #16 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984) #17 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88) #18 _PyObject_Call call.c:348 (python.exe:arm64+0x100088e48) #19 PyObject_Call call.c:373 (python.exe:arm64+0x100088ec0) #20 thread_run _threadmodule.c:388 (python.exe:arm64+0x1004582e0) #21 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10038fe08) Previous write of size 8 at 0x00010e600198 by thread T2: #0 sock_settimeout socketmodule.c:3264 (_socket.cpython-316t-darwin.so:arm64+0x83fc) #1 method_vectorcall_O descrobject.c:476 (python.exe:arm64+0x1000a0e38) #2 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88) #3 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68) #4 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8) #5 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c) #6 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8) #7 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984) #8 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88) #9 context_run context.c:731 (python.exe:arm64+0x1002dff38) #10 method_vectorcall_FASTCALL_KEYWORDS descrobject.c:421 (python.exe:arm64+0x1000a0b7c) #11 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088b88) #12 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68) #13 _PyEval_EvalFrameDefault generated_cases.c.h:1906 (python.exe:arm64+0x100295bc8) #14 _PyEval_Vector ceval.c:2172 (python.exe:arm64+0x10029000c) #15 _PyFunction_Vectorcall call.c (python.exe:arm64+0x1000891e8) #16 _PyObject_VectorcallPrepend call.c:855 (python.exe:arm64+0x10008a984) #17 method_vectorcall classobject.c:55 (python.exe:arm64+0x10008de88) #18 _PyObject_Call call.c:348 (python.exe:arm64+0x100088e48) #19 PyObject_Call call.c:373 (python.exe:arm64+0x100088ec0) #20 thread_run _threadmodule.c:388 (python.exe:arm64+0x1004582e0) #21 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x10038fe08) Thread T1 (tid=28859963, running) created by main thread at: #0 pthread_create <null>:126882288 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8) #1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10038f000) #2 PyThread_start_joinable_thread thread_pthread.h:323 (python.exe:arm64+0x10038ee38) #3 ThreadHandle_start _threadmodule.c:475 (python.exe:arm64+0x10045809c) #4 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x100457b7c) #5 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100456ae0) #6 cfunction_call methodobject.c:564 (python.exe:arm64+0x1001310f4) #7 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x100087f70) #8 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088c28) #9 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:768 (python.exe:arm64+0x100290b68) #10 _PyEval_EvalFrameDefault generated_cases.c.h:3474 (python.exe:arm64+0x100298e58) #11 PyEval_EvalCode ceval.c:679 (python.exe:arm64+0x10028fb74) #12 run_eval_code_obj pythonrun.c:1406 (python.exe:arm64+0x10036aea4) #13 run_mod pythonrun.c:1509 (python.exe:arm64+0x10036abd4) #14 _PyRun_SimpleFile pythonrun.c:544 (python.exe:arm64+0x100365d88) #15 _PyRun_AnyFile pythonrun.c:92 (python.exe:arm64+0x100365534) #16 Py_RunMain main.c:891 (python.exe:arm64+0x1003a7aec) #17 pymain_main main.c:921 (python.exe:arm64+0x1003a7f3c) #18 Py_BytesMain main.c:945 (python.exe:arm64+0x1003a8010) #19 main python.c:15 (python.exe:arm64+0x1000032ac) Thread T2 (tid=28859964, running) created by main thread at: #0 pthread_create <null>:126884528 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8) #1 do_start_joinable_thread thread_pthread.h:281 (python.exe:arm64+0x10038f000) #2 PyThread_start_joinable_thread thread_pthread.h:323 (python.exe:arm64+0x10038ee38) #3 ThreadHandle_start _threadmodule.c:475 (python.exe:arm64+0x10045809c) #4 do_start_new_thread _threadmodule.c:1919 (python.exe:arm64+0x100457b7c) #5 thread_PyThread_start_joinable_thread _threadmodule.c:2042 (python.exe:arm64+0x100456ae0) #6 cfunction_call methodobject.c:564 (python.exe:arm64+0x1001310f4) #7 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x100087f70) #8 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x100088c28) #9 _Py_VectorCall_StackRefSteal ceval.c:726 (python.exe:arm64+0x1002903e4) #10 _PyEval_EvalFrameDefault generated_cases.c.h (python.exe:arm64+0x1002995c4) #11 PyEval_EvalCode ceval.c:679 (python.exe:arm64+0x10028fb74) #12 run_eval_code_obj pythonrun.c:1406 (python.exe:arm64+0x10036aea4) #13 run_mod pythonrun.c:1509 (python.exe:arm64+0x10036abd4) #14 _PyRun_SimpleFile pythonrun.c:544 (python.exe:arm64+0x100365d88) #15 _PyRun_AnyFile pythonrun.c:92 (python.exe:arm64+0x100365534) #16 Py_RunMain main.c:891 (python.exe:arm64+0x1003a7aec) #17 pymain_main main.c:921 (python.exe:arm64+0x1003a7f3c) #18 Py_BytesMain main.c:945 (python.exe:arm64+0x1003a8010) #19 main python.c:15 (python.exe:arm64+0x1000032ac) SUMMARY: ThreadSanitizer: data race socketmodule.c:3320 in sock_gettimeout_method ================== done ThreadSanitizer: reported 1 warnings [1] 20351 abort ./python.exe repro_sock_timeout_race.pyProposed fix:
Wrap s->sock_timeout with _Py_atomic_load_int64_relaxed
I have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs