|
21 | 21 | #ifdef WITH_THREAD |
22 | 22 | #include "pythread.h" |
23 | 23 |
|
| 24 | +/* Redefined below for Windows debug builds after important #includes */ |
| 25 | +#define _PySSL_FIX_ERRNO |
24 | 26 |
|
25 | 27 | #define PySSL_BEGIN_ALLOW_THREADS_S(save) \ |
26 | 28 | do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) |
27 | 29 | #define PySSL_END_ALLOW_THREADS_S(save) \ |
28 | | - do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } } while (0) |
| 30 | + do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } _PySSL_FIX_ERRNO; } while (0) |
29 | 31 | #define PySSL_BEGIN_ALLOW_THREADS { \ |
30 | 32 | PyThreadState *_save = NULL; \ |
31 | 33 | PySSL_BEGIN_ALLOW_THREADS_S(_save); |
@@ -96,6 +98,40 @@ struct py_ssl_library_code { |
96 | 98 | int code; |
97 | 99 | }; |
98 | 100 |
|
| 101 | +#if defined(MS_WINDOWS) && defined(Py_DEBUG) |
| 102 | +/* Debug builds on Windows rely on getting errno directly from OpenSSL. |
| 103 | + * However, because it uses a different CRT, we need to transfer the |
| 104 | + * value of errno from OpenSSL into our debug CRT. |
| 105 | + * |
| 106 | + * Don't be fooled - this is horribly ugly code. The only reasonable |
| 107 | + * alternative is to do both debug and release builds of OpenSSL, which |
| 108 | + * requires much uglier code to transform their automatically generated |
| 109 | + * makefile. This is the lesser of all the evils. |
| 110 | + */ |
| 111 | + |
| 112 | +static void _PySSLFixErrno(void) { |
| 113 | + HMODULE ucrtbase = GetModuleHandleW(L"ucrtbase.dll"); |
| 114 | + if (!ucrtbase) { |
| 115 | + /* If ucrtbase.dll is not loaded but the SSL DLLs are, we likely |
| 116 | + * have a catastrophic failure, but this function is not the |
| 117 | + * place to raise it. */ |
| 118 | + return; |
| 119 | + } |
| 120 | + |
| 121 | + typedef int *(__stdcall *errno_func)(void); |
| 122 | + errno_func ssl_errno = (errno_func)GetProcAddress(ucrtbase, "_errno"); |
| 123 | + if (ssl_errno) { |
| 124 | + errno = *ssl_errno(); |
| 125 | + *ssl_errno() = 0; |
| 126 | + } else { |
| 127 | + errno = ENOTRECOVERABLE; |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +#undef _PySSL_FIX_ERRNO |
| 132 | +#define _PySSL_FIX_ERRNO _PySSLFixErrno() |
| 133 | +#endif |
| 134 | + |
99 | 135 | /* Include generated data (error codes) */ |
100 | 136 | #include "_ssl_data.h" |
101 | 137 |
|
|
0 commit comments