forked from pool/python313
- Add gh137583-only-lock-SSL-context.patch fixing the
regression in 3.13.6 by breaking non-blocking TLS connections (gh#python/cpython#137583). OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python313?expand=0&rev=117
This commit is contained in:
187
gh137583-only-lock-SSL-context.patch
Normal file
187
gh137583-only-lock-SSL-context.patch
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
Lib/test/test_ssl.py | 36 ++++++++++
|
||||||
|
Misc/NEWS.d/next/Library/2025-08-09-08-53-32.gh-issue-137583.s6OZud.rst | 4 +
|
||||||
|
Modules/_ssl.c | 33 ++++-----
|
||||||
|
Modules/_ssl/debughelpers.c | 1
|
||||||
|
4 files changed, 57 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
Index: Python-3.13.6/Lib/test/test_ssl.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.6.orig/Lib/test/test_ssl.py 2025-08-06 15:05:20.000000000 +0200
|
||||||
|
+++ Python-3.13.6/Lib/test/test_ssl.py 2025-08-12 11:34:50.729724565 +0200
|
||||||
|
@@ -4584,6 +4584,42 @@
|
||||||
|
with client_context.wrap_socket(socket.socket()) as s:
|
||||||
|
s.connect((HOST, server.port))
|
||||||
|
|
||||||
|
+ def test_thread_recv_while_main_thread_sends(self):
|
||||||
|
+ # GH-137583: Locking was added to calls to send() and recv() on SSL
|
||||||
|
+ # socket objects. This seemed fine at the surface level because those
|
||||||
|
+ # calls weren't re-entrant, but recv() calls would implicitly mimick
|
||||||
|
+ # holding a lock by blocking until it received data. This means that
|
||||||
|
+ # if a thread started to infinitely block until data was received, calls
|
||||||
|
+ # to send() would deadlock, because it would wait forever on the lock
|
||||||
|
+ # that the recv() call held.
|
||||||
|
+ data = b"1" * 1024
|
||||||
|
+ event = threading.Event()
|
||||||
|
+ def background(sock):
|
||||||
|
+ event.set()
|
||||||
|
+ received = sock.recv(len(data))
|
||||||
|
+ self.assertEqual(received, data)
|
||||||
|
+
|
||||||
|
+ client_context, server_context, hostname = testing_context()
|
||||||
|
+ server = ThreadedEchoServer(context=server_context)
|
||||||
|
+ with server:
|
||||||
|
+ with client_context.wrap_socket(socket.socket(),
|
||||||
|
+ server_hostname=hostname) as sock:
|
||||||
|
+ sock.connect((HOST, server.port))
|
||||||
|
+ sock.settimeout(1)
|
||||||
|
+ sock.setblocking(1)
|
||||||
|
+ # Ensure that the server is ready to accept requests
|
||||||
|
+ sock.sendall(b"123")
|
||||||
|
+ self.assertEqual(sock.recv(3), b"123")
|
||||||
|
+ with threading_helper.catch_threading_exception() as cm:
|
||||||
|
+ thread = threading.Thread(target=background,
|
||||||
|
+ args=(sock,), daemon=True)
|
||||||
|
+ thread.start()
|
||||||
|
+ event.wait()
|
||||||
|
+ sock.sendall(data)
|
||||||
|
+ thread.join()
|
||||||
|
+ if cm.exc_value is not None:
|
||||||
|
+ raise cm.exc_value
|
||||||
|
+
|
||||||
|
|
||||||
|
@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
|
||||||
|
class TestPostHandshakeAuth(unittest.TestCase):
|
||||||
|
Index: Python-3.13.6/Misc/NEWS.d/next/Library/2025-08-09-08-53-32.gh-issue-137583.s6OZud.rst
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||||
|
+++ Python-3.13.6/Misc/NEWS.d/next/Library/2025-08-09-08-53-32.gh-issue-137583.s6OZud.rst 2025-08-12 11:34:50.730240349 +0200
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+Fix a deadlock introduced in 3.13.6 when a call to
|
||||||
|
+:meth:`ssl.SSLSocket.recv <socket.socket.recv>` was blocked in one thread,
|
||||||
|
+and then another method on the object (such as :meth:`ssl.SSLSocket.send <socket.socket.send>`)
|
||||||
|
+was subsequently called in another thread.
|
||||||
|
Index: Python-3.13.6/Modules/_ssl.c
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.6.orig/Modules/_ssl.c 2025-08-06 15:05:20.000000000 +0200
|
||||||
|
+++ Python-3.13.6/Modules/_ssl.c 2025-08-12 11:34:50.730789308 +0200
|
||||||
|
@@ -332,9 +332,6 @@
|
||||||
|
* and shutdown methods check for chained exceptions.
|
||||||
|
*/
|
||||||
|
PyObject *exc;
|
||||||
|
- /* Lock to synchronize calls when the thread state is detached.
|
||||||
|
- See also gh-134698. */
|
||||||
|
- PyMutex tstate_mutex;
|
||||||
|
} PySSLSocket;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
@@ -846,7 +843,6 @@
|
||||||
|
self->server_hostname = NULL;
|
||||||
|
self->err = err;
|
||||||
|
self->exc = NULL;
|
||||||
|
- self->tstate_mutex = (PyMutex){0};
|
||||||
|
|
||||||
|
/* Make sure the SSL error state is initialized */
|
||||||
|
ERR_clear_error();
|
||||||
|
@@ -919,12 +915,12 @@
|
||||||
|
BIO_set_nbio(SSL_get_wbio(self->ssl), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS;
|
||||||
|
if (socket_type == PY_SSL_CLIENT)
|
||||||
|
SSL_set_connect_state(self->ssl);
|
||||||
|
else
|
||||||
|
SSL_set_accept_state(self->ssl);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
|
self->socket_type = socket_type;
|
||||||
|
if (sock != NULL) {
|
||||||
|
@@ -993,10 +989,11 @@
|
||||||
|
/* Actually negotiate SSL connection */
|
||||||
|
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
|
||||||
|
do {
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS
|
||||||
|
ret = SSL_do_handshake(self->ssl);
|
||||||
|
err = _PySSL_errno(ret < 1, self->ssl, ret);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
+ _PySSL_FIX_ERRNO;
|
||||||
|
self->err = err;
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals())
|
||||||
|
@@ -2462,10 +2459,11 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS;
|
||||||
|
retval = SSL_write_ex(self->ssl, b->buf, (size_t)b->len, &count);
|
||||||
|
err = _PySSL_errno(retval == 0, self->ssl, retval);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
+ _PySSL_FIX_ERRNO;
|
||||||
|
self->err = err;
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals())
|
||||||
|
@@ -2523,10 +2521,11 @@
|
||||||
|
int count = 0;
|
||||||
|
_PySSLError err;
|
||||||
|
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS;
|
||||||
|
count = SSL_pending(self->ssl);
|
||||||
|
err = _PySSL_errno(count < 0, self->ssl, count);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
+ _PySSL_FIX_ERRNO;
|
||||||
|
self->err = err;
|
||||||
|
|
||||||
|
if (count < 0)
|
||||||
|
@@ -2617,10 +2616,11 @@
|
||||||
|
deadline = _PyDeadline_Init(timeout);
|
||||||
|
|
||||||
|
do {
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS;
|
||||||
|
retval = SSL_read_ex(self->ssl, mem, (size_t)len, &count);
|
||||||
|
err = _PySSL_errno(retval == 0, self->ssl, retval);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
+ _PySSL_FIX_ERRNO;
|
||||||
|
self->err = err;
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals())
|
||||||
|
@@ -2719,7 +2719,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
- PySSL_BEGIN_ALLOW_THREADS(self)
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS;
|
||||||
|
/* Disable read-ahead so that unwrap can work correctly.
|
||||||
|
* Otherwise OpenSSL might read in too much data,
|
||||||
|
* eating clear text data that happens to be
|
||||||
|
@@ -2732,7 +2732,8 @@
|
||||||
|
SSL_set_read_ahead(self->ssl, 0);
|
||||||
|
ret = SSL_shutdown(self->ssl);
|
||||||
|
err = _PySSL_errno(ret < 0, self->ssl, ret);
|
||||||
|
- PySSL_END_ALLOW_THREADS(self)
|
||||||
|
+ Py_END_ALLOW_THREADS;
|
||||||
|
+ _PySSL_FIX_ERRNO;
|
||||||
|
self->err = err;
|
||||||
|
|
||||||
|
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
|
||||||
|
Index: Python-3.13.6/Modules/_ssl/debughelpers.c
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.6.orig/Modules/_ssl/debughelpers.c 2025-08-06 15:05:20.000000000 +0200
|
||||||
|
+++ Python-3.13.6/Modules/_ssl/debughelpers.c 2025-08-12 11:34:50.731270311 +0200
|
||||||
|
@@ -135,7 +135,6 @@
|
||||||
|
* critical debug helper.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- assert(PyMutex_IsLocked(&ssl_obj->tstate_mutex));
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
PyThread_acquire_lock(lock, 1);
|
||||||
|
res = BIO_printf(ssl_obj->ctx->keylog_bio, "%s\n", line);
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Aug 12 09:16:40 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add gh137583-only-lock-SSL-context.patch fixing the
|
||||||
|
regression in 3.13.6 by breaking non-blocking TLS connections
|
||||||
|
(gh#python/cpython#137583).
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Aug 7 10:08:11 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
Thu Aug 7 10:08:11 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ Patch42: gh126985-mv-pyvenv.cfg2getpath.patch
|
|||||||
# PATCH-FIX-UPSTREAM bsc1243155-sphinx-non-determinism.patch bsc#1243155 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM bsc1243155-sphinx-non-determinism.patch bsc#1243155 mcepl@suse.com
|
||||||
# Doc: Generate ids for audit_events using docname
|
# Doc: Generate ids for audit_events using docname
|
||||||
Patch43: bsc1243155-sphinx-non-determinism.patch
|
Patch43: bsc1243155-sphinx-non-determinism.patch
|
||||||
|
# PATCH-FIX-UPSTREAM gh137583-only-lock-SSL-context.patch gh#python/cpython#137583 mcepl@suse.com
|
||||||
|
# Only lock the SSL context, not the SSL socket
|
||||||
|
Patch44: gh137583-only-lock-SSL-context.patch
|
||||||
BuildRequires: autoconf-archive
|
BuildRequires: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
|
|||||||
Reference in New Issue
Block a user