2121#ifdef HAVE_SYS_WAIT_H
2222# include <sys/wait.h> // W_STOPCODE
2323#endif
24- #ifdef MS_WINDOWS
25- # define WIN32_LEAN_AND_MEAN
26- # include <windows.h> // Sleep()
27- #endif
2824
2925#ifdef bool
3026# error "The public headers should not include <stdbool.h>, see gh-48924"
@@ -56,22 +52,6 @@ get_testerror(PyObject *self) {
5652}
5753
5854
59- // Sleep 'ms' microseconds.
60- static void
61- pysleep_ms (int ms )
62- {
63- assert (ms >= 1 );
64- #ifdef MS_WINDOWS
65- Sleep (ms );
66- #else
67- struct timeval timeout ;
68- timeout .tv_sec = 0 ;
69- timeout .tv_usec = ms * 1000 ;
70- (void )select (0 , (fd_set * )0 , (fd_set * )0 , (fd_set * )0 , & timeout );
71- #endif
72- }
73-
74-
7555/* Raise _testcapi.error with test_name + ": " + msg, and return NULL. */
7656
7757static PyObject *
@@ -3456,21 +3436,13 @@ code_offset_to_line(PyObject* self, PyObject* const* args, Py_ssize_t nargsf)
34563436}
34573437
34583438
3459- typedef struct {
3460- PyThread_type_lock lock ;
3461- int completed ;
3462- } tracemalloc_track_race_data ;
3463-
34643439static void
3465- tracemalloc_track_race_thread (void * raw_data )
3440+ tracemalloc_track_race_thread (void * data )
34663441{
3467- tracemalloc_track_race_data * data = (tracemalloc_track_race_data * )raw_data ;
3468-
34693442 PyTraceMalloc_Track (123 , 10 , 1 );
34703443
3471- PyThread_acquire_lock (data -> lock , 1 );
3472- data -> completed += 1 ;
3473- PyThread_release_lock (data -> lock );
3444+ PyThread_type_lock lock = (PyThread_type_lock )data ;
3445+ PyThread_release_lock (lock );
34743446}
34753447
34763448// gh-128679: Test fix for tracemalloc.stop() race condition
@@ -3480,18 +3452,19 @@ tracemalloc_track_race(PyObject *self, PyObject *args)
34803452#define NTHREAD 50
34813453 PyObject * tracemalloc = NULL ;
34823454 PyObject * stop = NULL ;
3483- tracemalloc_track_race_data data = {0 };
3455+ PyThread_type_lock locks [NTHREAD ];
3456+ memset (locks , 0 , sizeof (locks ));
34843457
3458+ // Call tracemalloc.start()
34853459 tracemalloc = PyImport_ImportModule ("tracemalloc" );
34863460 if (tracemalloc == NULL ) {
34873461 goto error ;
34883462 }
3489-
34903463 PyObject * start = PyObject_GetAttrString (tracemalloc , "start" );
34913464 if (start == NULL ) {
34923465 goto error ;
34933466 }
3494- PyObject * res = PyObject_CallFunction (start , "i" , 1 );
3467+ PyObject * res = PyObject_CallNoArgs (start );
34953468 Py_DECREF (start );
34963469 if (res == NULL ) {
34973470 goto error ;
@@ -3503,47 +3476,56 @@ tracemalloc_track_race(PyObject *self, PyObject *args)
35033476 goto error ;
35043477 }
35053478
3506- data .lock = PyThread_allocate_lock ();
3507- if (!data .lock ) {
3508- PyErr_NoMemory ();
3509- goto error ;
3510- }
3511-
3479+ // Start threads
35123480 for (size_t i = 0 ; i < NTHREAD ; i ++ ) {
3513- unsigned long thread = PyThread_start_new_thread (
3514- tracemalloc_track_race_thread , & data );
3481+ PyThread_type_lock lock = PyThread_allocate_lock ();
3482+ if (!lock ) {
3483+ PyErr_NoMemory ();
3484+ goto error ;
3485+ }
3486+ locks [i ] = lock ;
3487+ PyThread_acquire_lock (lock , 1 );
3488+
3489+ unsigned long thread ;
3490+ thread = PyThread_start_new_thread (tracemalloc_track_race_thread ,
3491+ (void * )lock );
35153492 if (thread == (unsigned long )-1 ) {
35163493 PyErr_SetString (PyExc_RuntimeError , "can't start new thread" );
35173494 goto error ;
35183495 }
35193496 }
35203497
3498+ // Call tracemalloc.stop() while threads are running
35213499 res = PyObject_CallNoArgs (stop );
35223500 Py_CLEAR (stop );
35233501 if (res == NULL ) {
35243502 goto error ;
35253503 }
35263504
3505+ // Wait until threads complete with the GIL released
35273506 Py_BEGIN_ALLOW_THREADS
3528- while (1 ) {
3529- PyThread_acquire_lock (data .lock , 1 );
3530- int completed = data .completed ;
3531- PyThread_release_lock (data .lock );
3532- if (completed >= NTHREAD ) {
3533- break ;
3534- }
3535-
3536- pysleep_ms (10 );
3507+ for (size_t i = 0 ; i < NTHREAD ; i ++ ) {
3508+ PyThread_type_lock lock = locks [i ];
3509+ PyThread_acquire_lock (lock , 1 );
3510+ PyThread_release_lock (lock );
35373511 }
35383512 Py_END_ALLOW_THREADS
35393513
3514+ // Free threads locks
3515+ for (size_t i = 0 ; i < NTHREAD ; i ++ ) {
3516+ PyThread_type_lock lock = locks [i ];
3517+ PyThread_free_lock (lock );
3518+ }
35403519 Py_RETURN_NONE ;
35413520
35423521error :
35433522 Py_CLEAR (tracemalloc );
35443523 Py_CLEAR (stop );
3545- if (data .lock ) {
3546- PyThread_free_lock (data .lock );
3524+ for (size_t i = 0 ; i < NTHREAD ; i ++ ) {
3525+ PyThread_type_lock lock = locks [i ];
3526+ if (lock ) {
3527+ PyThread_free_lock (lock );
3528+ }
35473529 }
35483530 return NULL ;
35493531#undef NTHREAD
0 commit comments