Skip to content

Commit 9df058a

Browse files
committed
Rewrite the test without sleep
1 parent 61edb4c commit 9df058a

File tree

1 file changed

+35
-53
lines changed

1 file changed

+35
-53
lines changed

Modules/_testcapimodule.c

Lines changed: 35 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
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

7757
static 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-
34643439
static 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

35423521
error:
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

Comments
 (0)