https://github.com/python/cpython/commit/ea5a6363c3f8cc90b7c0cc573922b10f29…
commit: ea5a6363c3f8cc90b7c0cc573922b10f296073b6
branch: master
author: Ben Darnell <ben(a)bendarnell.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-31T12:57:52-07:00
summary:
bpo-39010: Fix errors logged on proactor loop restart (#22017)
Stopping and restarting a proactor event loop on windows can lead to
spurious errors logged (ConnectionResetError while reading from the
self pipe). This fixes the issue by ensuring that we don't attempt
to start multiple copies of the self-pipe reading loop.
files:
A Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst
M Lib/asyncio/proactor_events.py
M Lib/asyncio/windows_events.py
M Lib/test/test_asyncio/test_proactor_events.py
M Lib/test/test_asyncio/test_windows_events.py
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index d0b7100f5e056..4670bd683ab32 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -768,6 +768,14 @@ def _loop_self_reading(self, f=None):
try:
if f is not None:
f.result() # may raise
+ if self._self_reading_future is not f:
+ # When we scheduled this Future, we assigned it to
+ # _self_reading_future. If it's not there now, something has
+ # tried to cancel the loop while this callback was still in the
+ # queue (see windows_events.ProactorEventLoop.run_forever). In
+ # that case stop here instead of continuing to schedule a new
+ # iteration.
+ return
f = self._proactor.recv(self._ssock, 4096)
except exceptions.CancelledError:
# _close_self_pipe() has been called, stop waiting for data
diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
index a6759b78bd801..5e7cd795895d6 100644
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -318,8 +318,12 @@ def run_forever(self):
if self._self_reading_future is not None:
ov = self._self_reading_future._ov
self._self_reading_future.cancel()
- # self_reading_future was just cancelled so it will never be signalled
- # Unregister it otherwise IocpProactor.close will wait for it forever
+ # self_reading_future was just cancelled so if it hasn't been
+ # finished yet, it never will be (it's possible that it has
+ # already finished and its callback is waiting in the queue,
+ # where it could still happen if the event loop is restarted).
+ # Unregister it otherwise IocpProactor.close will wait for it
+ # forever
if ov is not None:
self._proactor._unregister(ov)
self._self_reading_future = None
diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py
index d0ab38743ecd1..4c8906d531ce5 100644
--- a/Lib/test/test_asyncio/test_proactor_events.py
+++ b/Lib/test/test_asyncio/test_proactor_events.py
@@ -753,6 +753,7 @@ def test_loop_self_reading(self):
def test_loop_self_reading_fut(self):
fut = mock.Mock()
+ self.loop._self_reading_future = fut
self.loop._loop_self_reading(fut)
self.assertTrue(fut.result.called)
self.proactor.recv.assert_called_with(self.ssock, 4096)
diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py
index 6b005702c9be7..33388a87d48f3 100644
--- a/Lib/test/test_asyncio/test_windows_events.py
+++ b/Lib/test/test_asyncio/test_windows_events.py
@@ -211,6 +211,26 @@ def test_wait_for_handle_cancel(self):
fut.cancel()
fut.cancel()
+ def test_read_self_pipe_restart(self):
+ # Regression test for https://bugs.python.org/issue39010
+ # Previously, restarting a proactor event loop in certain states
+ # would lead to spurious ConnectionResetErrors being logged.
+ self.loop.call_exception_handler = mock.Mock()
+ # Start an operation in another thread so that the self-pipe is used.
+ # This is theoretically timing-dependent (the task in the executor
+ # must complete before our start/stop cycles), but in practice it
+ # seems to work every time.
+ f = self.loop.run_in_executor(None, lambda: None)
+ self.loop.stop()
+ self.loop.run_forever()
+ self.loop.stop()
+ self.loop.run_forever()
+ # If we don't wait for f to complete here, we may get another
+ # warning logged about a thread that didn't shut down cleanly.
+ self.loop.run_until_complete(f)
+ self.loop.close()
+ self.assertFalse(self.loop.call_exception_handler.called)
+
class WinPolicyTests(test_utils.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst b/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst
new file mode 100644
index 0000000000000..0d9015b490e4c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst
@@ -0,0 +1,2 @@
+Restarting a ``ProactorEventLoop`` on Windows no longer logs spurious
+``ConnectionResetErrors``.
https://github.com/python/cpython/commit/c3a651ad2544d7d1be389b63e9a4a58a92…
commit: c3a651ad2544d7d1be389b63e9a4a58a92a31623
branch: master
author: Andre Delfino <adelfino(a)gmail.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-30T21:36:58+01:00
summary:
[doc] Fix markup in logging (GH-22008)
files:
M Doc/library/logging.rst
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index 3ff67f76cc3c5..a446c80ece604 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -1222,7 +1222,7 @@ functions.
| | opening the output file. If not specified, |
| | the value 'backslashreplace' is used. Note |
| | that if ``None`` is specified, it will be |
- | | passed as such to func:`open`, which means |
+ | | passed as such to :func:`open`, which means |
| | that it will be treated the same as passing |
| | 'errors'. |
+--------------+---------------------------------------------+
https://github.com/python/cpython/commit/38e32872eb3cf0dc9dd8cef9b05e47ba03…
commit: 38e32872eb3cf0dc9dd8cef9b05e47ba03638d34
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-30T20:42:27+01:00
summary:
bpo-41344: Raise ValueError when creating shared memory of size 0 (GH-21556) (GH-22019)
(cherry picked from commit 475a5fbb5644ea200c990d85d8c264e78ab6c7ea)
Co-authored-by: Vinay Sharma <vinay04sharma(a)icloud.com>
Co-authored-by: Vinay Sharma <vinay04sharma(a)icloud.com>
files:
A Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
M Lib/multiprocessing/shared_memory.py
M Lib/test/_test_multiprocessing.py
diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py
index f92eb012c8316..e5b5e6c098a02 100644
--- a/Lib/multiprocessing/shared_memory.py
+++ b/Lib/multiprocessing/shared_memory.py
@@ -75,6 +75,8 @@ def __init__(self, name=None, create=False, size=0):
raise ValueError("'size' must be a positive integer")
if create:
self._flags = _O_CREX | os.O_RDWR
+ if size == 0:
+ raise ValueError("'size' must be a positive number different from zero")
if name is None and not self._flags & os.O_EXCL:
raise ValueError("'name' can only be None if create=True")
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 8626aa37c186e..ee9b47bb5f153 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -3827,6 +3827,18 @@ class OptionalAttachSharedMemory(shared_memory.SharedMemory):
sms.close()
+ # Test creating a shared memory segment with negative size
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True, size=-1)
+
+ # Test creating a shared memory segment with size 0
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True, size=0)
+
+ # Test creating a shared memory segment without size argument
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True)
+
def test_shared_memory_across_processes(self):
# bpo-40135: don't define shared memory block's name in case of
# the failure when we run multiprocessing tests in parallel.
diff --git a/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
new file mode 100644
index 0000000000000..475bc9bddb0d5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
@@ -0,0 +1 @@
+Prevent creating :class:`shared_memory.SharedMemory` objects with :code:`size=0`.
https://github.com/python/cpython/commit/475a5fbb5644ea200c990d85d8c264e78a…
commit: 475a5fbb5644ea200c990d85d8c264e78ab6c7ea
branch: master
author: Vinay Sharma <vinay04sharma(a)icloud.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-30T20:03:11+01:00
summary:
bpo-41344: Raise ValueError when creating shared memory of size 0 (GH-21556)
files:
A Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
M Lib/multiprocessing/shared_memory.py
M Lib/test/_test_multiprocessing.py
diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py
index a3a5fcf4aba1e..122b3fcebf3fe 100644
--- a/Lib/multiprocessing/shared_memory.py
+++ b/Lib/multiprocessing/shared_memory.py
@@ -76,6 +76,8 @@ def __init__(self, name=None, create=False, size=0):
raise ValueError("'size' must be a positive integer")
if create:
self._flags = _O_CREX | os.O_RDWR
+ if size == 0:
+ raise ValueError("'size' must be a positive number different from zero")
if name is None and not self._flags & os.O_EXCL:
raise ValueError("'name' can only be None if create=True")
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 6a0e1016aff8d..fd3b4303f034c 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -3880,6 +3880,18 @@ class OptionalAttachSharedMemory(shared_memory.SharedMemory):
sms.close()
+ # Test creating a shared memory segment with negative size
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True, size=-1)
+
+ # Test creating a shared memory segment with size 0
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True, size=0)
+
+ # Test creating a shared memory segment without size argument
+ with self.assertRaises(ValueError):
+ sms_invalid = shared_memory.SharedMemory(create=True)
+
def test_shared_memory_across_processes(self):
# bpo-40135: don't define shared memory block's name in case of
# the failure when we run multiprocessing tests in parallel.
diff --git a/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
new file mode 100644
index 0000000000000..475bc9bddb0d5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst
@@ -0,0 +1 @@
+Prevent creating :class:`shared_memory.SharedMemory` objects with :code:`size=0`.
https://github.com/python/cpython/commit/92c38164a42572e2bc0b1b1490bec23694…
commit: 92c38164a42572e2bc0b1b1490bec2369480ae08
branch: master
author: Raymond Hettinger <rhettinger(a)users.noreply.github.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-30T10:00:11-07:00
summary:
Further improve accuracy of math.hypot() (GH-22013)
files:
M Modules/mathmodule.c
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 4ff2a069a76c7..6621951ee97d2 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -2455,6 +2455,9 @@ Given that csum >= 1.0, we have:
lo**2 <= 2**-54 < 2**-53 == 1/2*ulp(1.0) <= ulp(csum)/2
Since lo**2 is less than 1/2 ulp(csum), we have csum+lo*lo == csum.
+To minimize loss of information during the accumulation of fractional
+values, the lo**2 term has a separate accumulator.
+
The square root differential correction is needed because a
correctly rounded square root of a correctly rounded sum of
squares can still be off by as much as one ulp.
@@ -2475,7 +2478,8 @@ Borges' ALGORITHM 4 and 5.
1. Veltkamp-Dekker splitting: http://csclub.uwaterloo.ca/~pbarfuss/dekker1971.pdf
2. Compensated summation: http://www.ti3.tu-harburg.de/paper/rump/Ru08b.pdf
-3. Square root diffential correction: https://arxiv.org/pdf/1904.09481.pdf
+3. Square root differential correction: https://arxiv.org/pdf/1904.09481.pdf
+4. https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29…
*/
@@ -2483,7 +2487,7 @@ static inline double
vector_norm(Py_ssize_t n, double *vec, double max, int found_nan)
{
const double T27 = 134217729.0; /* ldexp(1.0, 27)+1.0) */
- double x, csum = 1.0, oldcsum, frac = 0.0, scale;
+ double x, csum = 1.0, oldcsum, frac = 0.0, frac_lo = 0.0, scale;
double t, hi, lo, h;
int max_e;
Py_ssize_t i;
@@ -2528,8 +2532,9 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan)
frac += (oldcsum - csum) + x;
assert(csum + lo * lo == csum);
- frac += lo * lo;
+ frac_lo += lo * lo;
}
+ frac += frac_lo;
h = sqrt(csum - 1.0 + frac);
x = h;
https://github.com/python/cpython/commit/75c80b0bda89debf312f075716b8c467d4…
commit: 75c80b0bda89debf312f075716b8c467d411f90e
branch: master
author: Tony Solomonik <tony.solomonik(a)gmail.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-29T23:53:08-05:00
summary:
closes bpo-41533: Fix a potential memory leak when allocating a stack (GH-21847)
Free the stack allocated in va_build_stack if do_mkstack fails
and the stack is not a small_stack
files:
A Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst
M Python/modsupport.c
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst
new file mode 100644
index 0000000000000..e166f0c0b621a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst
@@ -0,0 +1,2 @@
+Free the stack allocated in ``va_build_stack`` if ``do_mkstack`` fails and
+the stack is not a ``small_stack``.
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 2637039d4a151..2dabcf383409e 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -622,6 +622,9 @@ va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
va_end(lva);
if (res < 0) {
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
return NULL;
}
https://github.com/python/cpython/commit/c68c5af2dc5ada8875a662f2beaac6234e…
commit: c68c5af2dc5ada8875a662f2beaac6234eae2a5a
branch: master
author: Roger Iyengar <ri(a)rogeriyengar.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-29T16:47:38-07:00
summary:
Improve asyncio-dev 'Concurrency and Multithreading' docs (GH-20882)
I added some information to the `Concurrency and Multithreading` section of the `Developing with asyncio` guide.
This is all information that would have helped me when I started using asyncio. I incorrectly assumed that `loop.call_soon_threadsafe()` and `run_coroutine_threadsafe()` could be called from a thread in a process separate from the one that the event loop is running in. Explicitly stating that this will not work will probably help some people starting out with asyncio in the future.
I also added references to some other functions that can be used for inter-process communication without blocking the event loop. The section already mentions running blocking code in a ThreadPoolExecutor, but I think listing these other options in this section will also be helpful.
files:
M Doc/library/asyncio-dev.rst
diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst
index 77f8067197836..02a00033152ab 100644
--- a/Doc/library/asyncio-dev.rst
+++ b/Doc/library/asyncio-dev.rst
@@ -107,6 +107,16 @@ The :meth:`loop.run_in_executor` method can be used with a
blocking code in a different OS thread without blocking the OS thread
that the event loop runs in.
+There is currently no way to schedule coroutines or callbacks directly
+from a different process (such as one started with
+:mod:`multiprocessing`). The :ref:`Event Loop Methods <asyncio-event-loop>`
+section lists APIs that can read from pipes and watch file descriptors
+without blocking the event loop. In addition, asyncio's
+:ref:`Subprocess <asyncio-subprocess>` APIs provide a way to start a
+process and communicate with it from the event loop. Lastly, the
+aforementioned :meth:`loop.run_in_executor` method can also be used
+with a :class:`concurrent.futures.ProcessPoolExecutor` to execute
+code in a different process.
.. _asyncio-handle-blocking:
https://github.com/python/cpython/commit/a1473d2c9106abbdc619bdcc973c15a87e…
commit: a1473d2c9106abbdc619bdcc973c15a87e3f0f12
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: GitHub <noreply(a)github.com>
date: 2020-08-29T18:33:26-04:00
summary:
bpo-41634: Fix a typo in the curses documentation (GH-21958)
(cherry picked from commit 398575c210f79627830c5c470184f54ace950ac6)
Co-authored-by: Zackery Spytz <zspytz(a)gmail.com>
files:
M Doc/library/curses.rst
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index 957c6f60778fe..7cd20253aeea6 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -682,7 +682,7 @@ the following methods and attributes:
window.addch(y, x, ch[, attr])
Paint character *ch* at ``(y, x)`` with attributes *attr*, overwriting any
- character previously painter at that location. By default, the character
+ character previously painted at that location. By default, the character
position and attributes are the current settings for the window object.
.. note::