summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@microsoft.com>2017-07-17 09:15:48 (GMT)
committerGitHub <noreply@github.com>2017-07-17 09:15:48 (GMT)
commit68d663cf85d1ac5eaf83482eed39c0a6f8093601 (patch)
treefe26ff995655c31aca2d5c0f7bc4f8048cca5cc4 /Modules/_ssl.c
parent49f6449ef4b81537c19b82329caaf60596c516c2 (diff)
downloadcpython-68d663cf85d1ac5eaf83482eed39c0a6f8093601.zip
cpython-68d663cf85d1ac5eaf83482eed39c0a6f8093601.tar.gz
cpython-68d663cf85d1ac5eaf83482eed39c0a6f8093601.tar.bz2
[bpo-30916] Pre-build OpenSSL and Tcl/Tk for Windows (#2688)
Updates ssl and tkinter projects to use pre-built externals
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index a79a747..458d2e7 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -21,11 +21,13 @@
#ifdef WITH_THREAD
#include "pythread.h"
+/* Redefined below for Windows debug builds after important #includes */
+#define _PySSL_FIX_ERRNO
#define PySSL_BEGIN_ALLOW_THREADS_S(save) \
do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0)
#define PySSL_END_ALLOW_THREADS_S(save) \
- do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } } while (0)
+ do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } _PySSL_FIX_ERRNO; } while (0)
#define PySSL_BEGIN_ALLOW_THREADS { \
PyThreadState *_save = NULL; \
PySSL_BEGIN_ALLOW_THREADS_S(_save);
@@ -96,6 +98,40 @@ struct py_ssl_library_code {
int code;
};
+#if defined(MS_WINDOWS) && defined(Py_DEBUG)
+/* Debug builds on Windows rely on getting errno directly from OpenSSL.
+ * However, because it uses a different CRT, we need to transfer the
+ * value of errno from OpenSSL into our debug CRT.
+ *
+ * Don't be fooled - this is horribly ugly code. The only reasonable
+ * alternative is to do both debug and release builds of OpenSSL, which
+ * requires much uglier code to transform their automatically generated
+ * makefile. This is the lesser of all the evils.
+ */
+
+static void _PySSLFixErrno(void) {
+ HMODULE ucrtbase = GetModuleHandleW(L"ucrtbase.dll");
+ if (!ucrtbase) {
+ /* If ucrtbase.dll is not loaded but the SSL DLLs are, we likely
+ * have a catastrophic failure, but this function is not the
+ * place to raise it. */
+ return;
+ }
+
+ typedef int *(__stdcall *errno_func)(void);
+ errno_func ssl_errno = (errno_func)GetProcAddress(ucrtbase, "_errno");
+ if (ssl_errno) {
+ errno = *ssl_errno();
+ *ssl_errno() = 0;
+ } else {
+ errno = ENOTRECOVERABLE;
+ }
+}
+
+#undef _PySSL_FIX_ERRNO
+#define _PySSL_FIX_ERRNO _PySSLFixErrno()
+#endif
+
/* Include generated data (error codes) */
#include "_ssl_data.h"