Skip to content

Instantly share code, notes, and snippets.

@jonathanasdf
Last active March 4, 2017 00:17
Show Gist options
  • Save jonathanasdf/28500cff343bfc455366837082bf455f to your computer and use it in GitHub Desktop.
Save jonathanasdf/28500cff343bfc455366837082bf455f to your computer and use it in GitHub Desktop.
Python 3.7 Cygwin
diff --git a/Include/py_curses.h b/Include/py_curses.h
index 336c95d..0d87624 100644
--- a/Include/py_curses.h
+++ b/Include/py_curses.h
@@ -17,6 +17,13 @@
#define NCURSES_OPAQUE 0
#endif /* __APPLE__ */
+#ifdef __CYGWIN__
+/* the following define is necessary for Cygwin; without it, the
+ Cygwin-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python
+ can't get at the WINDOW flags field. */
+#define NCURSES_INTERNALS
+#endif /* __CYGWIN__ */
+
#ifdef __FreeBSD__
/*
** On FreeBSD, [n]curses.h and stdlib.h/wchar.h use different guards
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 4540385..b7f5684 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -358,7 +358,7 @@ PyAPI_FUNC(void) PyErr_SetInterrupt(void);
/* In signalmodule.c */
#ifndef Py_LIMITED_API
-int PySignal_SetWakeupFd(int fd);
+PyAPI_FUNC(int) PySignal_SetWakeupFd(int fd);
#endif
/* Support for adding program text to SyntaxErrors */
diff --git a/Include/pythread.h b/Include/pythread.h
index 88c4873..1fb9bef 100644
--- a/Include/pythread.h
+++ b/Include/pythread.h
@@ -2,6 +2,8 @@
#ifndef Py_PYTHREAD_H
#define Py_PYTHREAD_H
+#include <stdbool.h> /* necessary for TSS key */
+
typedef void *PyThread_type_lock;
typedef void *PyThread_type_sema;
@@ -25,8 +27,8 @@ PyAPI_FUNC(long) PyThread_get_thread_ident(void);
PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void);
PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock);
PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
-#define WAIT_LOCK 1
-#define NOWAIT_LOCK 0
+#define WAIT_LOCK 1
+#define NOWAIT_LOCK 0
/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting
on a lock (see PyThread_acquire_lock_timed() below).
@@ -73,15 +75,66 @@ PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
PyAPI_FUNC(PyObject*) PyThread_GetInfo(void);
#endif
-/* Thread Local Storage (TLS) API */
-PyAPI_FUNC(int) PyThread_create_key(void);
-PyAPI_FUNC(void) PyThread_delete_key(int);
-PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
-PyAPI_FUNC(void *) PyThread_get_key_value(int);
-PyAPI_FUNC(void) PyThread_delete_key_value(int key);
+/* Thread Local Storage (TLS) API
+ TLS API is DEPRECATED. Use Thread Specific Storage API.
+*/
+PyAPI_FUNC(long) PyThread_create_key(void) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void) PyThread_delete_key(long key) Py_DEPRECATED(3.7);
+PyAPI_FUNC(int) PyThread_set_key_value(long key, void *value) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void *) PyThread_get_key_value(long key) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void) PyThread_delete_key_value(long key) Py_DEPRECATED(3.7);
+
+/* Cleanup after a fork */
+PyAPI_FUNC(void) PyThread_ReInitTLS(void) Py_DEPRECATED(3.7);
+
+/* Thread Specific Storage (TSS) API
+
+ POSIX hasn't defined that pthread_key_t is compatible with int
+ (for details, see PEP 539). Therefore, TSS API uses opaque type to cover
+ the key details.
+*/
+
+#if defined(_POSIX_THREADS)
+# define NATIVE_TLS_KEY_T pthread_key_t
+#elif defined(NT_THREADS)
+# define NATIVE_TLS_KEY_T DWORD
+#else /* For the platform that has not supplied native TLS */
+# define NATIVE_TLS_KEY_T int
+#endif
+
+/* Py_tss_t is opaque type and you *must not* directly read and write.
+ When you'd check whether the key is created, use PyThread_tss_is_created.
+*/
+typedef struct {
+ bool _is_initialized;
+ NATIVE_TLS_KEY_T _key;
+} Py_tss_t;
+
+#undef NATIVE_TLS_KEY_T
+
+static inline bool
+PyThread_tss_is_created(Py_tss_t key)
+{
+ return key._is_initialized;
+}
+
+/* Py_tss_NEEDS_INIT is the defined invalid value, and you *must* initialize
+ the Py_tss_t variable by this value to use TSS API.
+
+ For example:
+ static Py_tss_t thekey = Py_tss_NEEDS_INIT;
+ int fail = PyThread_tss_create(&thekey);
+*/
+#define Py_tss_NEEDS_INIT {._is_initialized = false}
+
+PyAPI_FUNC(int) PyThread_tss_create(Py_tss_t *key);
+PyAPI_FUNC(void) PyThread_tss_delete(Py_tss_t *key);
+PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t key, void *value);
+PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t key);
+PyAPI_FUNC(void) PyThread_tss_delete_value(Py_tss_t key);
/* Cleanup after a fork */
-PyAPI_FUNC(void) PyThread_ReInitTLS(void);
+PyAPI_FUNC(void) PyThread_ReInitTSS(void);
#ifdef __cplusplus
}
diff --git a/Lib/cgi.py b/Lib/cgi.py
index 233a496..6731896 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -1,4 +1,4 @@
-#! /usr/local/bin/python
+#! /usr/local/bin/python3
# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
# intentionally NOT "/usr/bin/env python". On many systems
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index f870968..1a9bd55 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -431,7 +431,8 @@ pydll = LibraryLoader(PyDLL)
if _os.name == "nt":
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
elif _sys.platform == "cygwin":
- pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
+ pythonapi = PyDLL("libpython%d.%d%s.dll" % \
+ (_sys.version_info[:2] + tuple(_sys.abiflags)))
else:
pythonapi = PyDLL(None)
diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index 8856f65..d39cb66 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -80,6 +80,25 @@ if os.name == "posix" and sys.platform == "darwin":
continue
return None
+elif sys.platform == "cygwin":
+ def find_library(name):
+ for libdir in ['/usr/lib', '/usr/local/lib']:
+ for libext in ['lib%s.dll.a' % name, 'lib%s.a' % name]:
+ implib = os.path.join(libdir, libext)
+ if not os.path.exists(implib):
+ continue
+ cmd = "dlltool -I " + implib + " 2>/dev/null"
+ f = os.popen(cmd)
+ try:
+ data = f.read()
+ finally:
+ f.close()
+ res = data.replace("\n","")
+ if not res:
+ continue
+ return res
+ return None
+
elif os.name == "posix":
# Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
import re, tempfile
@@ -324,6 +343,10 @@ def test():
print(cdll.LoadLibrary("libcrypto.dylib"))
print(cdll.LoadLibrary("libSystem.dylib"))
print(cdll.LoadLibrary("System.framework/System"))
+ elif sys.platform == "cygwin":
+ print(cdll.LoadLibrary("cygbz2-1.dll"))
+ print(cdll.LoadLibrary("cygcrypt-0.dll"))
+ print(find_library("crypt"))
else:
print(cdll.LoadLibrary("libm.so"))
print(cdll.LoadLibrary("libcrypt.so"))
diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py
index 1c36990..6dd0bdb 100644
--- a/Lib/distutils/cygwinccompiler.py
+++ b/Lib/distutils/cygwinccompiler.py
@@ -92,9 +92,7 @@ class CygwinCCompiler(UnixCCompiler):
compiler_type = 'cygwin'
obj_extension = ".o"
static_lib_extension = ".a"
- shared_lib_extension = ".dll"
- static_lib_format = "lib%s%s"
- shared_lib_format = "%s%s"
+ shared_lib_extension = ".dll.a"
exe_extension = ".exe"
def __init__(self, verbose=0, dry_run=0, force=0):
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 8bf1a70..ab02557 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -156,7 +156,23 @@ def customize_compiler(compiler):
Mainly needed on Unix, so we can plug in the information that
varies across Unices and is stored in Python's Makefile.
"""
- if compiler.compiler_type == "unix":
+ global _config_vars
+ if compiler.compiler_type in ["cygwin", "mingw32"]:
+ # Note that cygwin use posix build and 'unix' compiler.
+ # If build is not based on posix then we must predefine
+ # some environment variables corresponding to posix
+ # build rules and defaults.
+ if not 'GCC' in sys.version:
+ _config_vars['CC'] = "gcc"
+ _config_vars['CXX'] = "g++"
+ _config_vars['OPT'] = "-fwrapv -O3 -Wall -Wstrict-prototypes"
+ _config_vars['CFLAGS'] = ""
+ _config_vars['CCSHARED'] = ""
+ _config_vars['LDSHARED'] = "gcc -shared -Wl,--enable-auto-image-base"
+ _config_vars['AR'] = "ar"
+ _config_vars['ARFLAGS'] = "rc"
+
+ if compiler.compiler_type in ["unix", "cygwin", "mingw32"]:
if sys.platform == "darwin":
# Perform first-time customization of compiler-related
# config vars on OS X now that we know we need a compiler.
@@ -166,7 +182,6 @@ def customize_compiler(compiler):
# that Python itself was built on. Also the user OS
# version and build tools may not support the same set
# of CPU architectures for universal builds.
- global _config_vars
# Use get_config_var() to ensure _config_vars is initialized.
if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
import _osx_support
diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
index 3f321c2..6359958 100644
--- a/Lib/distutils/unixccompiler.py
+++ b/Lib/distutils/unixccompiler.py
@@ -81,6 +81,7 @@ class UnixCCompiler(CCompiler):
xcode_stub_lib_format = dylib_lib_format
if sys.platform == "cygwin":
exe_extension = ".exe"
+ dylib_lib_extension = ".dll.a"
def preprocess(self, source, output_file=None, macros=None,
include_dirs=None, extra_preargs=None, extra_postargs=None):
@@ -224,7 +225,7 @@ class UnixCCompiler(CCompiler):
# the configuration data stored in the Python installation, so
# we use this hack.
compiler = os.path.basename(sysconfig.get_config_var("CC"))
- if sys.platform[:6] == "darwin":
+ if sys.platform[:6] == "darwin" or sys.platform[:6] == "cygwin":
# MacOSX's linker doesn't understand the -R flag at all
return "-L" + dir
elif sys.platform[:7] == "freebsd":
diff --git a/Lib/encodings/rot_13.py b/Lib/encodings/rot_13.py
index f0b4186..58c21d9 100755
--- a/Lib/encodings/rot_13.py
+++ b/Lib/encodings/rot_13.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
""" Python Character Mapping Codec for ROT13.
This codec de/encodes from str to str.
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index 6dbdab2..c5c560d 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -42,6 +42,12 @@ def _get_sep(path):
else:
return '/'
+def _get_altsep(path):
+ if isinstance(path, bytes):
+ return b'\\'
+ else:
+ return '\\'
+
# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac.
# On MS-DOS this may also turn slashes into backslashes; however, other
# normalizations (such as optimizing '../' away) are not allowed
@@ -63,7 +69,12 @@ def isabs(s):
"""Test whether a path is absolute"""
s = os.fspath(s)
sep = _get_sep(s)
- return s.startswith(sep)
+ altsep = _get_altsep(s)
+ return s.startswith(sep) or \
+ (sys.platform == 'msys' and \
+ len(s) > 2 and \
+ s[1] == ':' and \
+ (s[2] == sep or s[2] == altsep))
# Join pathnames.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 11015df..b61bda3 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -4026,6 +4026,49 @@ dict_get_version(PyObject *self, PyObject *args)
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)version);
}
+#ifdef WITH_THREAD
+static PyObject *
+test_pythread_tss_key_state(PyObject *self, PyObject *args)
+{
+ Py_tss_t tss_key = Py_tss_NEEDS_INIT;
+ if (PyThread_tss_is_created(tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "tss key hasn't been non created state at "
+ "initialization");
+ }
+ if (PyThread_tss_create(&tss_key) != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_create failed");
+ return NULL;
+ }
+ if (!PyThread_tss_is_created(tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_create succeeded, "
+ "but tss key didn't make created state");
+ }
+ if (PyThread_tss_create(&tss_key) != 0) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_create didn't succeed with "
+ "created key");
+ }
+#define CHECK_TSS_API(expr) \
+ (void)(expr); \
+ if (!PyThread_tss_is_created(tss_key)) { \
+ return raiseTestError("test_pythread_tss_key_state", \
+ "tss key state that has been created " \
+ "wasn't kept after calling " #expr); }
+ CHECK_TSS_API(PyThread_tss_set(tss_key, NULL));
+ CHECK_TSS_API(PyThread_tss_get(tss_key));
+ CHECK_TSS_API(PyThread_tss_delete_value(tss_key));
+#undef CHECK_TSS_API
+ PyThread_tss_delete(&tss_key);
+ if (PyThread_tss_is_created(tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_delete called, "
+ "but tss key didn't make non created state");
+ }
+ Py_RETURN_NONE;
+}
+#endif
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
@@ -4231,6 +4274,9 @@ static PyMethodDef TestMethods[] = {
{"tracemalloc_untrack", tracemalloc_untrack, METH_VARARGS},
{"tracemalloc_get_traceback", tracemalloc_get_traceback, METH_VARARGS},
{"dict_get_version", dict_get_version, METH_VARARGS},
+#ifdef WITH_THREAD
+ {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS},
+#endif
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index 950789b..58bdd9a 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -171,7 +171,7 @@ tracemalloc_error(const char *format, ...)
# error "need native thread local storage (TLS)"
#endif
-static int tracemalloc_reentrant_key = -1;
+static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
/* Any non-NULL pointer can be used */
#define REENTRANT Py_True
@@ -181,8 +181,8 @@ get_reentrant(void)
{
void *ptr;
- assert(tracemalloc_reentrant_key != -1);
- ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
+ assert(PyThread_tss_is_created(tracemalloc_reentrant_key));
+ ptr = PyThread_tss_get(tracemalloc_reentrant_key);
if (ptr != NULL) {
assert(ptr == REENTRANT);
return 1;
@@ -195,15 +195,15 @@ static void
set_reentrant(int reentrant)
{
assert(reentrant == 0 || reentrant == 1);
- assert(tracemalloc_reentrant_key != -1);
+ assert(PyThread_tss_is_created(tracemalloc_reentrant_key));
if (reentrant) {
assert(!get_reentrant());
- PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
+ PyThread_tss_set(tracemalloc_reentrant_key, REENTRANT);
}
else {
assert(get_reentrant());
- PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
+ PyThread_tss_set(tracemalloc_reentrant_key, NULL);
}
}
@@ -993,8 +993,7 @@ tracemalloc_init(void)
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
#ifdef REENTRANT_THREADLOCAL
- tracemalloc_reentrant_key = PyThread_create_key();
- if (tracemalloc_reentrant_key == -1) {
+ if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
#ifdef MS_WINDOWS
PyErr_SetFromWindowsErr(0);
#else
@@ -1079,8 +1078,7 @@ tracemalloc_deinit(void)
#endif
#ifdef REENTRANT_THREADLOCAL
- PyThread_delete_key(tracemalloc_reentrant_key);
- tracemalloc_reentrant_key = -1;
+ PyThread_tss_delete(&tracemalloc_reentrant_key);
#endif
Py_XDECREF(unknown_filename);
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 4fc8ebd..33ce431 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -231,7 +231,7 @@ faulthandler_dump_traceback(int fd, int all_threads,
PyThreadState_Get() doesn't give the state of the thread that caused the
fault if the thread released the GIL, and so this function cannot be
- used. Read the thread local storage (TLS) instead: call
+ used. Read the thread specific storage (TSS) instead: call
PyGILState_GetThisThreadState(). */
tstate = PyGILState_GetThisThreadState();
#else
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 0f91643..961cb6a 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -551,6 +551,28 @@ calculate_path(void)
if (isxfile(progpath))
break;
+#ifdef __CYGWIN__
+ /*
+ * Cygwin automatically removes the ".exe" extension from argv[0]
+ * to make programs feel like they are in a more Unix-like
+ * environment. Unfortunately, this can make it problemmatic for
+ * Cygwin to distinguish between a directory and an executable with
+ * the same name excluding the ".exe" extension. For example, the
+ * Cygwin Python build directory has a "Python" directory and a
+ * "python.exe" executable. This causes isxfile() to erroneously
+ * return false. If isdir() returns true and there is enough space
+ * to append the ".exe" extension, then we try again with the
+ * extension appended.
+ */
+#define EXE L".exe"
+ if (isdir(progpath) && wcslen(progpath) + wcslen(EXE) <= MAXPATHLEN)
+ {
+ wcscat(progpath, EXE);
+ if (isxfile(progpath))
+ break;
+ }
+#endif /* __CYGWIN__ */
+
if (!delim) {
progpath[0] = L'\0';
break;
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index 8bdf335..6877c51 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -4,6 +4,16 @@
have any value except INVALID_SOCKET.
*/
+/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.
+ 64 is too small (too many people have bumped into that limit).
+ Here we boost it.
+ Users who want even more than the boosted limit should #define
+ FD_SETSIZE higher before this; e.g., via compiler /D switch.
+*/
+#if (defined(MS_WINDOWS) || defined(__CYGWIN__)) && !defined(FD_SETSIZE)
+#define FD_SETSIZE 512
+#endif
+
#if defined(HAVE_POLL_H) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
@@ -26,16 +36,6 @@
#undef HAVE_BROKEN_POLL
#endif
-/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.
- 64 is too small (too many people have bumped into that limit).
- Here we boost it.
- Users who want even more than the boosted limit should #define
- FD_SETSIZE higher before this; e.g., via compiler /D switch.
-*/
-#if defined(MS_WINDOWS) && !defined(FD_SETSIZE)
-#define FD_SETSIZE 512
-#endif
-
#if defined(HAVE_POLL_H)
#include <poll.h>
#elif defined(HAVE_SYS_POLL_H)
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index bc36d41..3dda2be 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -1605,9 +1605,9 @@ PyOS_AfterFork(void)
* the interpreter had an opportunity to call the handlers. issue9535. */
_clear_pending_signals();
#ifdef WITH_THREAD
- /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API
+ /* PyThread_ReInitTSS() must be called early, to make sure that the TSS API
* can be called safely. */
- PyThread_ReInitTLS();
+ PyThread_ReInitTSS();
_PyGILState_Reinit();
PyEval_ReInitThreads();
main_thread = PyThread_get_thread_ident();
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 7aa213e..9d2c96c 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -240,7 +240,7 @@ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&
# include <ctype.h>
#endif
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__CYGWIN__)
# include <sys/ioctl.h>
#endif
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
index 7f8f134..92e6b09 100644
--- a/Python/dynload_shlib.c
+++ b/Python/dynload_shlib.c
@@ -34,6 +34,8 @@
const char *_PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__
+ "." SOABI ".dll",
+ ".abi" PYTHON_ABI_STRING ".dll",
".dll",
#else /* !__CYGWIN__ */
"." SOABI ".so",
diff --git a/Python/pystate.c b/Python/pystate.c
index 65c244e..4af0405 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -47,7 +47,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
GILState implementation
*/
static PyInterpreterState *autoInterpreterState = NULL;
-static int autoTLSkey = -1;
+static Py_tss_t autoTSSkey = Py_tss_NEEDS_INIT;
#else
#define HEAD_INIT() /* Nothing */
#define HEAD_LOCK() /* Nothing */
@@ -444,8 +444,8 @@ PyThreadState_Delete(PyThreadState *tstate)
if (tstate == GET_TSTATE())
Py_FatalError("PyThreadState_Delete: tstate is still current");
#ifdef WITH_THREAD
- if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
- PyThread_delete_key_value(autoTLSkey);
+ if (autoInterpreterState && PyThread_tss_get(autoTSSkey) == tstate)
+ PyThread_tss_delete_value(autoTSSkey);
#endif /* WITH_THREAD */
tstate_delete_common(tstate);
}
@@ -460,8 +460,8 @@ PyThreadState_DeleteCurrent()
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
tstate_delete_common(tstate);
- if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
- PyThread_delete_key_value(autoTLSkey);
+ if (autoInterpreterState && PyThread_tss_get(autoTSSkey) == tstate)
+ PyThread_tss_delete_value(autoTSSkey);
SET_TSTATE(NULL);
PyEval_ReleaseLock();
}
@@ -712,11 +712,10 @@ void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
{
assert(i && t); /* must init with valid states */
- autoTLSkey = PyThread_create_key();
- if (autoTLSkey == -1)
- Py_FatalError("Could not allocate TLS entry");
+ if (PyThread_tss_create(&autoTSSkey) != 0)
+ Py_FatalError("Could not allocate TSS entry");
autoInterpreterState = i;
- assert(PyThread_get_key_value(autoTLSkey) == NULL);
+ assert(PyThread_tss_get(autoTSSkey) == NULL);
assert(t->gilstate_counter == 0);
_PyGILState_NoteThreadState(t);
@@ -731,27 +730,26 @@ _PyGILState_GetInterpreterStateUnsafe(void)
void
_PyGILState_Fini(void)
{
- PyThread_delete_key(autoTLSkey);
- autoTLSkey = -1;
+ PyThread_tss_delete(&autoTSSkey);
autoInterpreterState = NULL;
}
-/* Reset the TLS key - called by PyOS_AfterFork().
+/* Reset the TSS key - called by PyOS_AfterFork().
* This should not be necessary, but some - buggy - pthread implementations
- * don't reset TLS upon fork(), see issue #10517.
+ * don't reset TSS upon fork(), see issue #10517.
*/
void
_PyGILState_Reinit(void)
{
PyThreadState *tstate = PyGILState_GetThisThreadState();
- PyThread_delete_key(autoTLSkey);
- if ((autoTLSkey = PyThread_create_key()) == -1)
- Py_FatalError("Could not allocate TLS entry");
+ PyThread_tss_delete(&autoTSSkey);
+ if (PyThread_tss_create(&autoTSSkey) != 0)
+ Py_FatalError("Could not allocate TSS entry");
/* If the thread had an associated auto thread state, reassociate it with
* the new key. */
- if (tstate && PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
- Py_FatalError("Couldn't create autoTLSkey mapping");
+ if (tstate && PyThread_tss_set(autoTSSkey, (void *)tstate) != 0)
+ Py_FatalError("Couldn't create autoTSSkey mapping");
}
/* When a thread state is created for a thread by some mechanism other than
@@ -762,13 +760,13 @@ _PyGILState_Reinit(void)
static void
_PyGILState_NoteThreadState(PyThreadState* tstate)
{
- /* If autoTLSkey isn't initialized, this must be the very first
+ /* If autoTSSkey isn't initialized, this must be the very first
threadstate created in Py_Initialize(). Don't do anything for now
(we'll be back here when _PyGILState_Init is called). */
if (!autoInterpreterState)
return;
- /* Stick the thread state for this thread in thread local storage.
+ /* Stick the thread state for this thread in thread specific storage.
The only situation where you can legitimately have more than one
thread state for an OS level thread is when there are multiple
@@ -780,9 +778,9 @@ _PyGILState_NoteThreadState(PyThreadState* tstate)
The first thread state created for that given OS level thread will
"win", which seems reasonable behaviour.
*/
- if (PyThread_get_key_value(autoTLSkey) == NULL) {
- if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
- Py_FatalError("Couldn't create autoTLSkey mapping");
+ if (PyThread_tss_get(autoTSSkey) == NULL) {
+ if (PyThread_tss_set(autoTSSkey, (void *)tstate) != 0)
+ Py_FatalError("Couldn't create autoTSSkey mapping");
}
/* PyGILState_Release must not try to delete this thread state. */
@@ -795,7 +793,7 @@ PyGILState_GetThisThreadState(void)
{
if (autoInterpreterState == NULL)
return NULL;
- return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+ return (PyThreadState *)PyThread_tss_get(autoTSSkey);
}
int
@@ -806,7 +804,7 @@ PyGILState_Check(void)
if (!_PyGILState_check_enabled)
return 1;
- if (autoTLSkey == -1)
+ if (!PyThread_tss_is_created(autoTSSkey))
return 1;
tstate = GET_TSTATE();
@@ -827,7 +825,7 @@ PyGILState_Ensure(void)
called Py_Initialize() and usually PyEval_InitThreads().
*/
assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
- tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+ tcur = (PyThreadState *)PyThread_tss_get(autoTSSkey);
if (tcur == NULL) {
/* At startup, Python has no concrete GIL. If PyGILState_Ensure() is
called from a new thread for the first time, we need the create the
@@ -859,8 +857,7 @@ PyGILState_Ensure(void)
void
PyGILState_Release(PyGILState_STATE oldstate)
{
- PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
- autoTLSkey);
+ PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(autoTSSkey);
if (tcur == NULL)
Py_FatalError("auto-releasing thread-state, "
"but no thread-state for this thread");
diff --git a/Python/random.c b/Python/random.c
index c97d5e7..5f032fe 100644
--- a/Python/random.c
+++ b/Python/random.c
@@ -80,7 +80,6 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
#else /* !MS_WINDOWS */
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
-#define PY_GETRANDOM 1
/* Call getrandom() to get random bytes:
@@ -187,7 +186,6 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
}
#elif defined(HAVE_GETENTROPY)
-#define PY_GETENTROPY 1
/* Fill buffer with size pseudo-random bytes generated by getentropy():
diff --git a/Python/thread.c b/Python/thread.c
index 63eeb1e..fe2112c 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#endif
+#include <stdbool.h> /* necessary for TSS key */
#include <stdlib.h>
#include "pythread.h"
@@ -125,25 +126,25 @@ PyThread_set_stacksize(size_t size)
TLS implementation, provide our own.
This code stolen from "thread_sgi.h", where it was the only
- implementation of an existing Python TLS API.
+ implementation of a Python TLS API that has been deprecated.
*/
/* ------------------------------------------------------------------------
Per-thread data ("key") support.
-Use PyThread_create_key() to create a new key. This is typically shared
+Use PyThread_tss_create(&thekey) to create a new key. This is typically shared
across threads.
-Use PyThread_set_key_value(thekey, value) to associate void* value with
+Use PyThread_tss_set(thekey, value) to associate void* value with
thekey in the current thread. Each thread has a distinct mapping of thekey
to a void* value. Caution: if the current thread already has a mapping
for thekey, value is ignored.
-Use PyThread_get_key_value(thekey) to retrieve the void* value associated
+Use PyThread_tss_get(thekey) to retrieve the void* value associated
with thekey in the current thread. This returns NULL if no value is
associated with thekey in the current thread.
-Use PyThread_delete_key_value(thekey) to forget the current thread's associated
-value for thekey. PyThread_delete_key(thekey) forgets the values associated
+Use PyThread_tss_delete_value(thekey) to forget the current thread's associated
+value for thekey. PyThread_tss_delete(&thekey) forgets the values associated
with thekey across *all* threads.
While some of these functions have error-return values, none set any
@@ -155,12 +156,12 @@ happen to be PyObject*, these functions don't do refcount operations on
them either.
The GIL does not need to be held when calling these functions; they supply
-their own locking. This isn't true of PyThread_create_key(), though (see
+their own locking. This isn't true of PyThread_tss_create(), though (see
next paragraph).
-There's a hidden assumption that PyThread_create_key() will be called before
+There's a hidden assumption that PyThread_tss_create() will be called before
any of the other functions are called. There's also a hidden assumption
-that calls to PyThread_create_key() are serialized externally.
+that calls to PyThread_tss_create() are serialized externally.
------------------------------------------------------------------------ */
/* A singly-linked list of struct key objects remembers all the key->value
@@ -181,7 +182,7 @@ struct key {
static struct key *keyhead = NULL;
static PyThread_type_lock keymutex = NULL;
-static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
+static int nkeys = 0; /* PyThread_tss_create() hands out nkeys+1 next */
/* Internal helper.
* If the current thread has a mapping for key, the appropriate struct key*
@@ -200,7 +201,7 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
* another thread to mutate the list, via key deletion, concurrent with
* find_key() crawling over the list. Hilarity ensued. For example, when
* the for-loop here does "p = p->next", p could end up pointing at a
- * record that PyThread_delete_key_value() was concurrently free()'ing.
+ * record that PyThread_tss_delete_value() was concurrently free()'ing.
* That could lead to anything, from failing to find a key that exists, to
* segfaults. Now we lock the whole routine.
*/
@@ -225,10 +226,10 @@ find_key(int set_value, int key, void *value)
* in a tight loop with the lock held. A similar check is done
* in pystate.c tstate_delete_common(). */
if (p == prev_p)
- Py_FatalError("tls find_key: small circular list(!)");
+ Py_FatalError("tss find_key: small circular list(!)");
prev_p = p;
if (p->next == keyhead)
- Py_FatalError("tls find_key: circular list(!)");
+ Py_FatalError("tss find_key: circular list(!)");
}
if (!set_value && value == NULL) {
assert(p == NULL);
@@ -247,31 +248,97 @@ find_key(int set_value, int key, void *value)
return p;
}
-/* Return a new key. This must be called before any other functions in
+
+/* Thread Local Storage (TLS) API, DEPRECATED since Python 3.7
+
+ In CPython self implementation, TLS API has been changed to call TSS API.
+*/
+
+int
+PyThread_create_key(void)
+{
+ Py_tss_t proxy = Py_tss_NEEDS_INIT;
+ if (PyThread_tss_create(&proxy) != 0)
+ return -1;
+ /* In CPython self implementation, platform-specific key type is int. */
+ return proxy._key;
+}
+
+void
+PyThread_delete_key(int key)
+{
+ Py_tss_t proxy = {._is_initialized = true, ._key = key};
+ PyThread_tss_delete(&proxy);
+}
+
+int
+PyThread_set_key_value(int key, void *value)
+{
+ Py_tss_t proxy = {._is_initialized = true, ._key = key};
+ return PyThread_tss_set(proxy, value);
+}
+
+void *
+PyThread_get_key_value(int key)
+{
+ Py_tss_t proxy = {._is_initialized = true, ._key = key};
+ return PyThread_tss_get(proxy);
+}
+
+void
+PyThread_delete_key_value(int key)
+{
+ Py_tss_t proxy = {._is_initialized = true, ._key = key};
+ PyThread_tss_delete_value(proxy);
+}
+
+
+void
+PyThread_ReInitTLS(void)
+{
+ PyThread_ReInitTSS();
+}
+
+
+/* Thread Specific Storage (TSS) API */
+
+/* Assign a new key. This must be called before any other functions in
* this family, and callers must arrange to serialize calls to this
* function. No violations are detected.
*/
int
-PyThread_create_key(void)
+PyThread_tss_create(Py_tss_t *key)
{
/* All parts of this function are wrong if it's called by multiple
* threads simultaneously.
*/
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized)
+ return 0;
+
if (keymutex == NULL)
keymutex = PyThread_allocate_lock();
- return ++nkeys;
+ key->_key = ++nkeys;
+ key->_is_initialized = true;
+ return 0;
}
/* Forget the associations for key across *all* threads. */
void
-PyThread_delete_key(int key)
+PyThread_tss_delete(Py_tss_t *key)
{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized)
+ return;
+
struct key *p, **q;
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
- if (p->key == key) {
+ if (p->key == key->_key) {
*q = p->next;
PyMem_RawFree((void *)p);
/* NB This does *not* free p->value! */
@@ -279,15 +346,16 @@ PyThread_delete_key(int key)
else
q = &p->next;
}
+ key->_key = -1;
+ key->_is_initialized = false;
PyThread_release_lock(keymutex);
}
int
-PyThread_set_key_value(int key, void *value)
+PyThread_tss_set(Py_tss_t key, void *value)
{
- struct key *p;
+ struct key *p = find_key(1, key._key, value);
- p = find_key(1, key, value);
if (p == NULL)
return -1;
else
@@ -298,9 +366,9 @@ PyThread_set_key_value(int key, void *value)
* if the current thread doesn't have an association for key.
*/
void *
-PyThread_get_key_value(int key)
+PyThread_tss_get(Py_tss_t key)
{
- struct key *p = find_key(0, key, NULL);
+ struct key *p = find_key(0, key._key, NULL);
if (p == NULL)
return NULL;
@@ -310,7 +378,7 @@ PyThread_get_key_value(int key)
/* Forget the current thread's association for key, if any. */
void
-PyThread_delete_key_value(int key)
+PyThread_tss_delete_value(Py_tss_t key)
{
long id = PyThread_get_thread_ident();
struct key *p, **q;
@@ -318,7 +386,7 @@ PyThread_delete_key_value(int key)
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
- if (p->key == key && p->id == id) {
+ if (p->key == key._key && p->id == id) {
*q = p->next;
PyMem_RawFree((void *)p);
/* NB This does *not* free p->value! */
@@ -330,13 +398,14 @@ PyThread_delete_key_value(int key)
PyThread_release_lock(keymutex);
}
+
/* Forget everything not associated with the current thread id.
* This function is called from PyOS_AfterFork(). It is necessary
* because other thread ids which were in use at the time of the fork
* may be reused for new threads created in the forked process.
*/
void
-PyThread_ReInitTLS(void)
+PyThread_ReInitTSS(void)
{
long id = PyThread_get_thread_ident();
struct key *p, **q;
diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h
index ea96f9c..3e9e083 100644
--- a/Python/thread_foobar.h
+++ b/Python/thread_foobar.h
@@ -71,7 +71,7 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", lock, microseconds, intr_flag));
dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
- lock, microseconds, intr_flag, success));
+ lock, microseconds, intr_flag, success));
return success;
}
@@ -85,6 +85,9 @@ PyThread_release_lock(PyThread_type_lock lock)
#define Py_HAVE_NATIVE_TLS
#ifdef Py_HAVE_NATIVE_TLS
+
+/* Thread Local Storage (TLS) API, DEPRECATED since Python 3.7 */
+
int
PyThread_create_key(void)
{
@@ -123,10 +126,74 @@ PyThread_delete_key_value(int key)
}
+
void
PyThread_ReInitTLS(void)
{
}
+
+/* Thread Specific Storage (TSS) API */
+
+int
+PyThread_tss_create(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized)
+ return 0;
+
+ Py_tss_t new_key;
+ /* A failure in this case returns -1 */
+ if (!new_key._key)
+ return -1;
+ key->_key = new_key._key;
+ key->_is_initialized = true;
+ return 0;
+}
+
+void
+PyThread_tss_delete(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized)
+ return;
+
+ key->_is_initialized = false;
+}
+
+int
+PyThread_tss_set(Py_tss_t key, void *value)
+{
+ int ok;
+
+ /* A failure in this case returns -1 */
+ if (!ok)
+ return -1;
+ return 0;
+}
+
+void *
+PyThread_tss_get(Py_tss_t key)
+{
+ void *result;
+
+ return result;
+}
+
+void
+PyThread_tss_delete_value(Py_tss_t key)
+{
+
+}
+
+
+void
+PyThread_ReInitTSS(void)
+{
+
+}
+
#endif
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 74a6ee8..44a6655 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -8,6 +8,7 @@
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
+#include <stdbool.h> /* necessary for TSS key */
/* options */
#ifndef _PY_USE_CV_LOCKS
@@ -352,10 +353,13 @@ _pythread_nt_set_stacksize(size_t size)
#define Py_HAVE_NATIVE_TLS
#ifdef Py_HAVE_NATIVE_TLS
+
+/* Thread Local Storage (TLS) API, DEPRECATED since Python 3.7 */
+
int
PyThread_create_key(void)
{
- DWORD result= TlsAlloc();
+ DWORD result = TlsAlloc();
if (result == TLS_OUT_OF_INDEXES)
return -1;
return (int)result;
@@ -370,12 +374,8 @@ PyThread_delete_key(int key)
int
PyThread_set_key_value(int key, void *value)
{
- BOOL ok;
-
- ok = TlsSetValue(key, value);
- if (!ok)
- return -1;
- return 0;
+ BOOL ok = TlsSetValue(key, value);
+ return ok ? 0 : -1;
}
void *
@@ -402,6 +402,7 @@ PyThread_delete_key_value(int key)
TlsSetValue(key, NULL);
}
+
/* reinitialization of TLS is not necessary after fork when using
* the native TLS functions. And forking isn't supported on Windows either.
*/
@@ -409,4 +410,76 @@ void
PyThread_ReInitTLS(void)
{}
+
+/* Thread Specific Storage (TSS) API */
+
+int
+PyThread_tss_create(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized)
+ return 0;
+
+ DWORD result = TlsAlloc();
+ if (result == TLS_OUT_OF_INDEXES)
+ return -1;
+ /* In Windows, platform-specific key type is DWORD. */
+ key->_key = result;
+ key->_is_initialized = true;
+ return 0;
+}
+
+void
+PyThread_tss_delete(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized)
+ return;
+
+ TlsFree(key->_key);
+ key->_key = TLS_OUT_OF_INDEXES;
+ key->_is_initialized = false;
+}
+
+int
+PyThread_tss_set(Py_tss_t key, void *value)
+{
+ BOOL ok = TlsSetValue(key._key, value);
+ return ok ? 0 : -1;
+}
+
+void *
+PyThread_tss_get(Py_tss_t key)
+{
+ /* because TSS is used in the Py_END_ALLOW_THREAD macro,
+ * it is necessary to preserve the windows error state, because
+ * it is assumed to be preserved across the call to the macro.
+ * Ideally, the macro should be fixed, but it is simpler to
+ * do it here.
+ */
+ DWORD error = GetLastError();
+ void *result = TlsGetValue(key._key);
+ SetLastError(error);
+ return result;
+}
+
+void
+PyThread_tss_delete_value(Py_tss_t key)
+{
+ /* NULL is used as "key missing", and it is also the default
+ * given by TlsGetValue() if nothing has been set yet.
+ */
+ TlsSetValue(key._key, NULL);
+}
+
+
+/* reinitialization of TSS is not necessary after fork when using
+ * the native TLS functions. And forking isn't supported on Windows either.
+ */
+void
+PyThread_ReInitTSS(void)
+{}
+
#endif
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 27e0dc8..a73f16e 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -1,6 +1,7 @@
/* Posix threads interface */
+#include <stdbool.h> /* necessary for TSS key */
#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
@@ -603,48 +604,128 @@ _pythread_pthread_set_stacksize(size_t size)
#define Py_HAVE_NATIVE_TLS
-int
+/* Thread Local Storage (TLS) API, DEPRECATED since Python 3.7
+
+ Issue #25658: POSIX hasn't defined that pthread_key_t is compatible
+ with int. Note that if incompatible with int, PyThread_create_key
+ returns immediately a failure status and the other TLS functions
+ all are no-ops. Moreover, PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT will
+ be unnecessary after removing this API.
+*/
+
+long
PyThread_create_key(void)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_key_t key;
int fail = pthread_key_create(&key, NULL);
if (fail)
- return -1;
+ return -1L;
if (key > INT_MAX) {
/* Issue #22206: handle integer overflow */
pthread_key_delete(key);
errno = ENOMEM;
- return -1;
+ return -1L;
}
- return (int)key;
+ return (long)key;
+#else
+ return -1; /* never return valid key value. */
+#endif
}
void
-PyThread_delete_key(int key)
+PyThread_delete_key(long key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_key_delete(key);
+#endif
}
void
-PyThread_delete_key_value(int key)
+PyThread_delete_key_value(long key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_setspecific(key, NULL);
+#endif
}
int
-PyThread_set_key_value(int key, void *value)
+PyThread_set_key_value(long key, void *value)
{
- int fail;
- fail = pthread_setspecific(key, value);
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
+ int fail = pthread_setspecific(key, value);
return fail ? -1 : 0;
+#else
+ return -1;
+#endif
}
void *
-PyThread_get_key_value(int key)
+PyThread_get_key_value(long key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
return pthread_getspecific(key);
+#else
+ return NULL;
+#endif
}
+
void
PyThread_ReInitTLS(void)
{}
+
+
+/* Thread Specific Storage (TSS) API */
+
+int
+PyThread_tss_create(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized)
+ return 0;
+
+ int fail = pthread_key_create(&(key->_key), NULL);
+ if (fail)
+ return -1;
+ key->_is_initialized = true;
+ return 0;
+}
+
+void
+PyThread_tss_delete(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized)
+ return;
+
+ pthread_key_delete(key->_key);
+ /* pthread has not provided the defined invalid value for the key. */
+ key->_is_initialized = false;
+}
+
+int
+PyThread_tss_set(Py_tss_t key, void *value)
+{
+ int fail = pthread_setspecific(key._key, value);
+ return fail ? -1 : 0;
+}
+
+void *
+PyThread_tss_get(Py_tss_t key)
+{
+ return pthread_getspecific(key._key);
+}
+
+void
+PyThread_tss_delete_value(Py_tss_t key)
+{
+ pthread_setspecific(key._key, NULL);
+}
+
+
+void
+PyThread_ReInitTSS(void)
+{}
diff --git a/Python/traceback.c b/Python/traceback.c
index 9f8c568..42a5dcf 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -760,7 +760,7 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
PyThreadState_Get() doesn't give the state of the thread that caused
the fault if the thread released the GIL, and so this function
- cannot be used. Read the thread local storage (TLS) instead: call
+ cannot be used. Read the thread specific storage (TSS) instead: call
PyGILState_GetThisThreadState(). */
current_tstate = PyGILState_GetThisThreadState();
}
diff --git a/configure b/configure
index 1126372..5b733b4 100755
--- a/configure
+++ b/configure
@@ -9022,6 +9022,75 @@ _ACEOF
fi
+
+# Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int.
+# This checking will be unnecessary after removing deprecated TLS API.
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of pthread_key_t" >&5
+$as_echo_n "checking size of pthread_key_t... " >&6; }
+if ${ac_cv_sizeof_pthread_key_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_key_t))" "ac_cv_sizeof_pthread_key_t" "#include <pthread.h>
+"; then :
+
+else
+ if test "$ac_cv_type_pthread_key_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (pthread_key_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_pthread_key_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_key_t" >&5
+$as_echo "$ac_cv_sizeof_pthread_key_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_PTHREAD_KEY_T $ac_cv_sizeof_pthread_key_t
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_key_t is compatible with int" >&5
+$as_echo_n "checking whether pthread_key_t is compatible with int... " >&6; }
+if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+pthread_key_t k; k * 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_pthread_key_t_is_arithmetic_type=yes
+else
+ ac_pthread_key_t_is_arithmetic_type=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pthread_key_t_is_arithmetic_type" >&5
+$as_echo "$ac_pthread_key_t_is_arithmetic_type" >&6; }
+ if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then
+
+$as_echo "#define PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT 1" >>confdefs.h
+
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
CC="$ac_save_cc"
diff --git a/configure.ac b/configure.ac
index 5610c57..6b5c7fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2278,6 +2278,25 @@ if test "$have_pthread_t" = yes ; then
#endif
])
fi
+
+# Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int.
+# This checking will be unnecessary after removing deprecated TLS API.
+AC_CHECK_SIZEOF(pthread_key_t, [], [[#include <pthread.h>]])
+AC_MSG_CHECKING(whether pthread_key_t is compatible with int)
+if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_key_t k; k * 1;]])],
+ [ac_pthread_key_t_is_arithmetic_type=yes],
+ [ac_pthread_key_t_is_arithmetic_type=no]
+ )
+ AC_MSG_RESULT($ac_pthread_key_t_is_arithmetic_type)
+ if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then
+ AC_DEFINE(PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT, 1,
+ [Define if pthread_key_t is compatible with int.])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
CC="$ac_save_cc"
AC_SUBST(OTHER_LIBTOOL_OPT)
@@ -4637,7 +4656,7 @@ AC_MSG_RESULT($SOABI)
AC_SUBST(EXT_SUFFIX)
case $ac_sys_system in
- Linux*|GNU*|Darwin)
+ Linux*|GNU*|CYGWIN*|Darwin)
EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};;
*)
EXT_SUFFIX=${SHLIB_SUFFIX};;
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 21354a5..8b0d1ba 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1241,6 +1241,9 @@
/* Define if POSIX semaphores aren't enabled on your system */
#undef POSIX_SEMAPHORES_NOT_ENABLED
+/* Define if pthread_key_t is compatible with int. */
+#undef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
+
/* Defined if PTHREAD_SCOPE_SYSTEM supported. */
#undef PTHREAD_SYSTEM_SCHED_SUPPORTED
@@ -1296,6 +1299,9 @@
/* The size of `pid_t', as computed by sizeof. */
#undef SIZEOF_PID_T
+/* The size of `pthread_key_t', as computed by sizeof. */
+#undef SIZEOF_PTHREAD_KEY_T
+
/* The size of `pthread_t', as computed by sizeof. */
#undef SIZEOF_PTHREAD_T
diff --git a/setup.py b/setup.py
index 3b3d097..1ca3462 100644
--- a/setup.py
+++ b/setup.py
@@ -1242,7 +1242,7 @@ class PyBuildExt(build_ext):
dbm_setup_debug = False # verbose debug prints from this script?
dbm_order = ['gdbm']
# The standard Unix dbm module:
- if host_platform not in ['cygwin']:
+ if host_platform not in ['win32']:
config_args = [arg.strip("'")
for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
dbm_args = [arg for arg in config_args
@@ -1273,6 +1273,16 @@ class PyBuildExt(build_ext):
libraries=ndbm_libs)
break
+ if find_file("ndbm.h", inc_dirs, []) is not None:
+ if dbm_setup_debug: print("building dbm using gdbm")
+ dbmext = Extension(
+ '_dbm', ['_dbmmodule.c'],
+ define_macros=[
+ ('HAVE_NDBM_H', None),
+ ],
+ libraries = gdbm_libs)
+ break
+
elif cand == "gdbm":
if self.compiler.find_library_file(lib_dirs, 'gdbm'):
gdbm_libs = ['gdbm']
@@ -1841,12 +1851,6 @@ class PyBuildExt(build_ext):
include_dirs.append('/usr/X11/include')
added_lib_dirs.append('/usr/X11/lib')
- # If Cygwin, then verify that X is installed before proceeding
- if host_platform == 'cygwin':
- x11_inc = find_file('X11/Xlib.h', [], include_dirs)
- if x11_inc is None:
- return
-
# Check for BLT extension
if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
'BLT8.0'):
@@ -1864,9 +1868,8 @@ class PyBuildExt(build_ext):
if host_platform in ['aix3', 'aix4']:
libs.append('ld')
- # Finally, link with the X11 libraries (not appropriate on cygwin)
- if host_platform != "cygwin":
- libs.append('X11')
+ # Finally, link with the X11 libraries
+ libs.append('X11')
ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
define_macros=[('WITH_APPINIT', 1)] + defs,
# I take no responsibilities for the following (especially changes in Python/random.c)
git clone https://github.com/python/cpython && cd cpython
git checkout d0e8212ed70445cc3d48b0d4ae7c9cb480004010
# "Could not allocate TLS entry" patch from http://bugs.python.org/issue25658
# Many other patches from https://github.com/Alexpux/MSYS2-packages/tree/7a0c270dad882351d3b0348b10def6e360eba72b/python3
git apply python-3.7-cygwin.patch
./configure
make -j8 && make install
# you may need to rebaseall
@jonathanasdf
Copy link
Author

Try adding a newline at the end of the patch. I just tested it again and it works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment