Skip to content

Commit 112b6ac

Browse files
authored
Merge branch 'main' into fix/issue-151943-xmlrpc-client-refs
2 parents e006838 + 75d96f8 commit 112b6ac

4 files changed

Lines changed: 64 additions & 46 deletions

File tree

‎Doc/c-api/bytes.rst‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ Variant using a pointer to compute the final size::
494494
495495
char *str = PyBytesWriter_GetData(writer);
496496
memcpy(str, "abc", 3);
497-
str += 1;
497+
str += 3;
498498
return PyBytesWriter_FinishWithPointer(writer, str);
499499
}
500500
@@ -543,7 +543,7 @@ Update ``_PyBytes_Resize()`` code
543543
544544
Example of code using the soft deprecated ``_PyBytes_Resize()`` API::
545545
546-
void create_string(Py_ssize_t size)
546+
PyObject* create_string(Py_ssize_t size)
547547
{
548548
PyObject *bytes = PyBytes_FromStringAndSize(NULL, size);
549549
if (bytes == NULL) {
@@ -561,7 +561,7 @@ Example of code using the soft deprecated ``_PyBytes_Resize()`` API::
561561
562562
It can now be updated to::
563563
564-
void create_string(Py_ssize_t size)
564+
PyObject* create_string(Py_ssize_t size)
565565
{
566566
PyBytesWriter *writer = PyBytesWriter_Create(size);
567567
if (writer == NULL) {

‎Doc/c-api/init_config.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ Example::
840840
if (PyStatus_Exception(status)) {
841841
Py_ExitStatusException(status);
842842
}
843-
PyMem_Free(ptr);
843+
PyMem_RawFree(ptr);
844844
return 0;
845845
}
846846

‎Lib/test/_test_multiprocessing.py‎

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,8 +1222,10 @@ def test_put(self):
12221222
queue.put(5, False, None)
12231223
queue.put_nowait(6)
12241224

1225-
# the values may be in buffer but not yet in pipe so sleep a bit
1226-
time.sleep(DELTA)
1225+
# The values may be in the buffer but not yet in the pipe.
1226+
for _ in support.sleeping_retry(support.SHORT_TIMEOUT):
1227+
if not queue_empty(queue):
1228+
break
12271229

12281230
self.assertEqual(queue_empty(queue), False)
12291231
self.assertEqual(queue_full(queue, MAXSIZE), True)
@@ -1344,8 +1346,10 @@ def test_fork(self):
13441346
for i in range(10):
13451347
queue.put(i)
13461348

1347-
# wait to make sure thread starts before we fork a new process
1348-
time.sleep(DELTA)
1349+
# Wait for the feeder thread to write to the pipe before forking.
1350+
for _ in support.sleeping_retry(support.SHORT_TIMEOUT):
1351+
if not queue_empty(queue):
1352+
break
13491353

13501354
# fork process
13511355
p = self.Process(target=self._test_fork, args=(queue,))
@@ -1568,15 +1572,15 @@ def test_repr_lock(self):
15681572
args=(lock, l),
15691573
name=tname)
15701574
t.start()
1571-
time.sleep(0.1)
1575+
threading_helper.join_thread(t)
15721576
self.assertEqual(f'<Lock(owner=MainProcess|{tname})>', l[0])
15731577
lock.release()
15741578

15751579
t = threading.Thread(target=self._acquire,
15761580
args=(lock,),
15771581
name=tname)
15781582
t.start()
1579-
time.sleep(0.1)
1583+
threading_helper.join_thread(t)
15801584
self.assertEqual('<Lock(owner=SomeOtherThread)>', repr(lock))
15811585
lock.release()
15821586

@@ -3177,25 +3181,28 @@ def produce_args():
31773181
last_produced_task_arg.value = arg
31783182
yield arg
31793183

3180-
method = getattr(p, method_name)
3181-
it = method(functools.partial(sqr, wait=0.2), produce_args())
3184+
def wait_for_produced_args(threshold):
3185+
for _ in support.sleeping_retry(support.SHORT_TIMEOUT, error=False):
3186+
if last_produced_task_arg.value > threshold:
3187+
break
3188+
self.assertGreater(last_produced_task_arg.value, threshold)
31823189

3183-
time.sleep(0.2)
3184-
# `iterable` could've been advanced only `processes` times,
3185-
# but in fact it advances further (`> processes`) because of
3186-
# not waiting for workers or user code to catch up.
3187-
self.assertGreater(last_produced_task_arg.value, processes)
3190+
try:
3191+
method = getattr(p, method_name)
3192+
it = method(functools.partial(sqr, wait=0.2), produce_args())
31883193

3189-
next(it)
3190-
time.sleep(0.2)
3191-
self.assertGreater(last_produced_task_arg.value, processes + 1)
3194+
# Without a buffer limit, the iterable advances without waiting
3195+
# for workers or user code to catch up.
3196+
wait_for_produced_args(processes)
31923197

3193-
next(it)
3194-
time.sleep(0.2)
3195-
self.assertGreater(last_produced_task_arg.value, processes + 2)
3198+
next(it)
3199+
wait_for_produced_args(processes + 1)
31963200

3197-
p.terminate()
3198-
p.join()
3201+
next(it)
3202+
wait_for_produced_args(processes + 2)
3203+
finally:
3204+
p.terminate()
3205+
p.join()
31993206

32003207
@unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
32013208
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
@@ -3215,23 +3222,29 @@ def produce_args():
32153222
last_produced_task_arg.value = arg
32163223
yield arg
32173224

3218-
method = getattr(p, method_name)
3219-
it = method(functools.partial(sqr, wait=0.2), produce_args(),
3220-
buffersize=processes)
3225+
def wait_for_produced_args(expected):
3226+
# Consuming a result allows the task handler to advance the
3227+
# iterable, but does not wait for it to do so.
3228+
for _ in support.sleeping_retry(support.SHORT_TIMEOUT, error=False):
3229+
if last_produced_task_arg.value >= expected:
3230+
break
3231+
self.assertEqual(last_produced_task_arg.value, expected)
32213232

3222-
time.sleep(0.2)
3223-
self.assertEqual(last_produced_task_arg.value, processes)
3233+
try:
3234+
method = getattr(p, method_name)
3235+
it = method(functools.partial(sqr, wait=0.2), produce_args(),
3236+
buffersize=processes)
32243237

3225-
next(it)
3226-
time.sleep(0.2)
3227-
self.assertEqual(last_produced_task_arg.value, processes + 1)
3238+
wait_for_produced_args(processes)
32283239

3229-
next(it)
3230-
time.sleep(0.2)
3231-
self.assertEqual(last_produced_task_arg.value, processes + 2)
3240+
next(it)
3241+
wait_for_produced_args(processes + 1)
32323242

3233-
p.terminate()
3234-
p.join()
3243+
next(it)
3244+
wait_for_produced_args(processes + 2)
3245+
finally:
3246+
p.terminate()
3247+
p.join()
32353248

32363249
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
32373250
@support.subTests('method_name', ("imap", "imap_unordered"))
@@ -3437,8 +3450,11 @@ def test_release_task_refs(self):
34373450
self.pool.map(identity, objs)
34383451

34393452
del objs
3440-
time.sleep(DELTA) # let threaded cleanup code run
3441-
support.gc_collect() # For PyPy or other GCs.
3453+
for _ in support.sleeping_retry(support.SHORT_TIMEOUT, error=False):
3454+
support.gc_collect() # For PyPy or other GCs.
3455+
if (all(wr() is None for wr in refs)
3456+
and CountedObject.n_instances == 0):
3457+
break
34423458
self.assertEqual(set(wr() for wr in refs), {None})
34433459
# With a process pool, copies of the objects are returned, check
34443460
# they were released too.
@@ -4032,7 +4048,7 @@ def test_connection(self):
40324048
self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1)
40334049

40344050
conn.send(None)
4035-
time.sleep(.1)
4051+
self.assertTrue(conn.poll(support.SHORT_TIMEOUT))
40364052

40374053
self.assertEqual(poll(TIMEOUT1), True)
40384054
self.assertTimingAlmostEqual(poll.elapsed, 0)
@@ -4333,11 +4349,10 @@ def test_issue14725(self):
43334349
p = self.Process(target=self._test, args=(l.address,))
43344350
p.daemon = True
43354351
p.start()
4336-
time.sleep(1)
4337-
# On Windows the client process should by now have connected,
4338-
# written data and closed the pipe handle by now. This causes
4339-
# ConnectNamdedPipe() to fail with ERROR_NO_DATA. See Issue
4340-
# 14725.
4352+
join_process(p)
4353+
# On Windows the client process has now connected, written data
4354+
# and closed the pipe handle. This causes ConnectNamedPipe()
4355+
# to fail with ERROR_NO_DATA. See Issue 14725.
43414356
conn = l.accept()
43424357
self.assertEqual(conn.recv(), 'hello')
43434358
conn.close()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Replace fixed sleeps used for synchronization in multiprocessing tests with
2+
bounded waits to avoid failures on slow or overloaded systems. Ensure pool
3+
cleanup runs even when assertions fail in the imap buffer tests.

0 commit comments

Comments
 (0)