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
Bug report
Bug description:
Created from gh-153852 TSAN-0035
sock->sock_timeoutis a plainPyTime_tand 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:
Proposed fix:
Wrap
s->sock_timeoutwith_Py_atomic_load_int64_relaxedI have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs