Issue #10272: The ssl module now raises socket.timeout instead of a generic
SSLError on socket timeouts.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index c2b976a..a514555 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -370,7 +370,7 @@
             sockstate = SOCKET_OPERATION_OK;
         }
         if (sockstate == SOCKET_HAS_TIMED_OUT) {
-            PyErr_SetString(PySSLErrorObject,
+            PyErr_SetString(PySocketModule.timeout_error,
                             ERRSTR("The handshake operation timed out"));
             goto error;
         } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
@@ -1075,7 +1075,7 @@
 
     sockstate = check_socket_and_wait_for_timeout(sock, 1);
     if (sockstate == SOCKET_HAS_TIMED_OUT) {
-        PyErr_SetString(PySSLErrorObject,
+        PyErr_SetString(PySocketModule.timeout_error,
                         "The write operation timed out");
         goto error;
     } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
@@ -1104,7 +1104,7 @@
             sockstate = SOCKET_OPERATION_OK;
         }
         if (sockstate == SOCKET_HAS_TIMED_OUT) {
-            PyErr_SetString(PySSLErrorObject,
+            PyErr_SetString(PySocketModule.timeout_error,
                             "The write operation timed out");
             goto error;
         } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
@@ -1211,7 +1211,7 @@
     if (!count) {
         sockstate = check_socket_and_wait_for_timeout(sock, 0);
         if (sockstate == SOCKET_HAS_TIMED_OUT) {
-            PyErr_SetString(PySSLErrorObject,
+            PyErr_SetString(PySocketModule.timeout_error,
                             "The read operation timed out");
             goto error;
         } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
@@ -1245,7 +1245,7 @@
             sockstate = SOCKET_OPERATION_OK;
         }
         if (sockstate == SOCKET_HAS_TIMED_OUT) {
-            PyErr_SetString(PySSLErrorObject,
+            PyErr_SetString(PySocketModule.timeout_error,
                             "The read operation timed out");
             goto error;
         } else if (sockstate == SOCKET_IS_NONBLOCKING) {
@@ -1340,10 +1340,10 @@
             break;
         if (sockstate == SOCKET_HAS_TIMED_OUT) {
             if (ssl_err == SSL_ERROR_WANT_READ)
-                PyErr_SetString(PySSLErrorObject,
+                PyErr_SetString(PySocketModule.timeout_error,
                                 "The read operation timed out");
             else
-                PyErr_SetString(PySSLErrorObject,
+                PyErr_SetString(PySocketModule.timeout_error,
                                 "The write operation timed out");
             goto error;
         }
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index e24bf54..abdd1b2 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -4358,6 +4358,7 @@
 PySocketModule_APIObject PySocketModuleAPI =
 {
     &sock_type,
+    NULL,
     NULL
 };
 
@@ -4425,6 +4426,7 @@
                                         socket_error, NULL);
     if (socket_timeout == NULL)
         return NULL;
+    PySocketModuleAPI.timeout_error = socket_timeout;
     Py_INCREF(socket_timeout);
     PyModule_AddObject(m, "timeout", socket_timeout);
     Py_INCREF((PyObject *)&sock_type);
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 4f426f5..f064795 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -196,6 +196,7 @@
 typedef struct {
     PyTypeObject *Sock_Type;
     PyObject *error;
+    PyObject *timeout_error;
 } PySocketModule_APIObject;
 
 #define PySocketModule_ImportModuleAndAPI() PyCapsule_Import(PySocket_CAPSULE_NAME, 1)