diff -r 4243df51fe43 Include/py_curses.h --- a/Include/py_curses.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Include/py_curses.h Fri Mar 03 22:57:17 2017 -0600 @@ -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 -r 4243df51fe43 Include/pyerrors.h --- a/Include/pyerrors.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Include/pyerrors.h Fri Mar 03 22:57:17 2017 -0600 @@ -358,8 +358,13 @@ /* In signalmodule.c */ #ifndef Py_LIMITED_API +#ifdef __CYGWIN__ +/* Cygwin Requires this change. */ +PyAPI_FUNC(int) PySignal_SetWakeupFd(int fd); +#else int PySignal_SetWakeupFd(int fd); #endif +#endif /* Support for adding program text to SyntaxErrors */ PyAPI_FUNC(void) PyErr_SyntaxLocation( diff -r 4243df51fe43 Include/pythread.h --- a/Include/pythread.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Include/pythread.h Fri Mar 03 22:57:17 2017 -0600 @@ -2,6 +2,11 @@ #ifndef Py_PYTHREAD_H #define Py_PYTHREAD_H +#ifdef __CYGWIN__ +/* For Cygwin use TSS instead of TLS. */ +#include /* necessary for TSS key */ +#endif + typedef void *PyThread_type_lock; typedef void *PyThread_type_sema; @@ -25,8 +30,8 @@ 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,6 +78,68 @@ PyAPI_FUNC(PyObject*) PyThread_GetInfo(void); #endif +#ifdef __CYGWIN__ +/* 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_ReInitTSS(void); +#else /* Thread Local Storage (TLS) API */ PyAPI_FUNC(int) PyThread_create_key(void); PyAPI_FUNC(void) PyThread_delete_key(int); @@ -82,6 +149,7 @@ /* Cleanup after a fork */ PyAPI_FUNC(void) PyThread_ReInitTLS(void); +#endif #ifdef __cplusplus } diff -r 4243df51fe43 Lib/ctypes/__init__.py --- a/Lib/ctypes/__init__.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/ctypes/__init__.py Fri Mar 03 22:57:17 2017 -0600 @@ -431,7 +431,8 @@ 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 -r 4243df51fe43 Lib/ctypes/util.py --- a/Lib/ctypes/util.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/ctypes/util.py Fri Mar 03 22:57:17 2017 -0600 @@ -80,6 +80,25 @@ 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 @@ 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 -r 4243df51fe43 Lib/distutils/cygwinccompiler.py --- a/Lib/distutils/cygwinccompiler.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/distutils/cygwinccompiler.py Fri Mar 03 22:57:17 2017 -0600 @@ -92,9 +92,7 @@ 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 -r 4243df51fe43 Lib/distutils/sysconfig.py --- a/Lib/distutils/sysconfig.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/distutils/sysconfig.py Fri Mar 03 22:57:17 2017 -0600 @@ -156,7 +156,23 @@ 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 @@ # 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 -r 4243df51fe43 Lib/distutils/unixccompiler.py --- a/Lib/distutils/unixccompiler.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/distutils/unixccompiler.py Fri Mar 03 22:57:17 2017 -0600 @@ -81,6 +81,7 @@ 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 @@ # 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 -r 4243df51fe43 Lib/posixpath.py --- a/Lib/posixpath.py Fri Feb 10 14:19:36 2017 +0100 +++ b/Lib/posixpath.py Fri Mar 03 22:57:17 2017 -0600 @@ -42,6 +42,12 @@ 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 @@ """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 -r 4243df51fe43 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/_testcapimodule.c Fri Mar 03 22:57:17 2017 -0600 @@ -4026,6 +4026,51 @@ return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)version); } +#ifdef __CYGWIN__ +#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 +#endif static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -4231,6 +4276,11 @@ {"tracemalloc_untrack", tracemalloc_untrack, METH_VARARGS}, {"tracemalloc_get_traceback", tracemalloc_get_traceback, METH_VARARGS}, {"dict_get_version", dict_get_version, METH_VARARGS}, +#ifdef __CYGWIN__ +#ifdef WITH_THREAD + {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS}, +#endif +#endif {NULL, NULL} /* sentinel */ }; diff -r 4243df51fe43 Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/_tracemalloc.c Fri Mar 03 22:57:17 2017 -0600 @@ -171,7 +171,11 @@ # error "need native thread local storage (TLS)" #endif +#ifdef __CYGWIN__ +static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT; +#else static int tracemalloc_reentrant_key = -1; +#endif /* Any non-NULL pointer can be used */ #define REENTRANT Py_True @@ -181,8 +185,13 @@ { void *ptr; +#ifdef __CYGWIN__ + assert(PyThread_tss_is_created(tracemalloc_reentrant_key)); + ptr = PyThread_tss_get(tracemalloc_reentrant_key); +#else assert(tracemalloc_reentrant_key != -1); ptr = PyThread_get_key_value(tracemalloc_reentrant_key); +#endif if (ptr != NULL) { assert(ptr == REENTRANT); return 1; @@ -195,15 +204,27 @@ set_reentrant(int reentrant) { assert(reentrant == 0 || reentrant == 1); +#ifdef __CYGWIN__ + assert(PyThread_tss_is_created(tracemalloc_reentrant_key)); +#else assert(tracemalloc_reentrant_key != -1); +#endif if (reentrant) { assert(!get_reentrant()); +#ifdef __CYGWIN__ + PyThread_tss_set(tracemalloc_reentrant_key, REENTRANT); +#else PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT); +#endif } else { assert(get_reentrant()); +#ifdef __CYGWIN__ + PyThread_tss_set(tracemalloc_reentrant_key, NULL); +#else PyThread_set_key_value(tracemalloc_reentrant_key, NULL); +#endif } } @@ -993,8 +1014,12 @@ PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); #ifdef REENTRANT_THREADLOCAL +#ifdef __CYGWIN__ + if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) { +#else tracemalloc_reentrant_key = PyThread_create_key(); if (tracemalloc_reentrant_key == -1) { +#endif #ifdef MS_WINDOWS PyErr_SetFromWindowsErr(0); #else @@ -1079,9 +1104,13 @@ #endif #ifdef REENTRANT_THREADLOCAL +#ifdef __CYGWIN__ + PyThread_tss_delete(&tracemalloc_reentrant_key); +#else PyThread_delete_key(tracemalloc_reentrant_key); tracemalloc_reentrant_key = -1; #endif +#endif Py_XDECREF(unknown_filename); } diff -r 4243df51fe43 Modules/faulthandler.c --- a/Modules/faulthandler.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/faulthandler.c Fri Mar 03 22:57:17 2017 -0600 @@ -231,7 +231,8 @@ 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 local storage (TLS) or the thread specific + storage (TSS) for cygwin instead: call PyGILState_GetThisThreadState(). */ tstate = PyGILState_GetThisThreadState(); #else diff -r 4243df51fe43 Modules/getpath.c --- a/Modules/getpath.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/getpath.c Fri Mar 03 22:57:17 2017 -0600 @@ -551,6 +551,28 @@ 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 -r 4243df51fe43 Modules/selectmodule.c --- a/Modules/selectmodule.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/selectmodule.c Fri Mar 03 22:57:17 2017 -0600 @@ -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 #elif defined(HAVE_SYS_POLL_H) diff -r 4243df51fe43 Modules/signalmodule.c --- a/Modules/signalmodule.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/signalmodule.c Fri Mar 03 22:57:17 2017 -0600 @@ -1605,9 +1605,15 @@ * the interpreter had an opportunity to call the handlers. issue9535. */ _clear_pending_signals(); #ifdef WITH_THREAD +#ifdef __CYGWIN__ + /* PyThread_ReInitTSS() must be called early, to make sure that the TSS API + * can be called safely. */ + PyThread_ReInitTSS(); +#else /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API * can be called safely. */ PyThread_ReInitTLS(); +#endif _PyGILState_Reinit(); PyEval_ReInitThreads(); main_thread = PyThread_get_thread_ident(); diff -r 4243df51fe43 Modules/socketmodule.c --- a/Modules/socketmodule.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Modules/socketmodule.c Fri Mar 03 22:57:17 2017 -0600 @@ -240,7 +240,7 @@ # include #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__CYGWIN__) # include #endif diff -r 4243df51fe43 Python/dynload_shlib.c --- a/Python/dynload_shlib.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/dynload_shlib.c Fri Mar 03 22:57:17 2017 -0600 @@ -34,6 +34,8 @@ const char *_PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ + "." SOABI ".dll", + ".abi" PYTHON_ABI_STRING ".dll", ".dll", #else /* !__CYGWIN__ */ "." SOABI ".so", diff -r 4243df51fe43 Python/pystate.c --- a/Python/pystate.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/pystate.c Fri Mar 03 22:57:17 2017 -0600 @@ -47,7 +47,11 @@ GILState implementation */ static PyInterpreterState *autoInterpreterState = NULL; +#ifdef __CYGWIN__ +static Py_tss_t autoTSSkey = Py_tss_NEEDS_INIT; +#else static int autoTLSkey = -1; +#endif #else #define HEAD_INIT() /* Nothing */ #define HEAD_LOCK() /* Nothing */ @@ -444,8 +448,13 @@ if (tstate == GET_TSTATE()) Py_FatalError("PyThreadState_Delete: tstate is still current"); #ifdef WITH_THREAD +#ifdef __CYGWIN__ + if (autoInterpreterState && PyThread_tss_get(autoTSSkey) == tstate) + PyThread_tss_delete_value(autoTSSkey); +#else if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); +#endif #endif /* WITH_THREAD */ tstate_delete_common(tstate); } @@ -460,8 +469,13 @@ Py_FatalError( "PyThreadState_DeleteCurrent: no current tstate"); tstate_delete_common(tstate); +#ifdef __CYGWIN__ + if (autoInterpreterState && PyThread_tss_get(autoTSSkey) == tstate) + PyThread_tss_delete_value(autoTSSkey); +#else if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); +#endif SET_TSTATE(NULL); PyEval_ReleaseLock(); } @@ -712,11 +726,20 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { assert(i && t); /* must init with valid states */ +#ifdef __CYGWIN__ + if (PyThread_tss_create(&autoTSSkey) != 0) + Py_FatalError("Could not allocate TSS entry"); +#else autoTLSkey = PyThread_create_key(); if (autoTLSkey == -1) Py_FatalError("Could not allocate TLS entry"); +#endif autoInterpreterState = i; +#ifdef __CYGWIN__ + assert(PyThread_tss_get(autoTSSkey) == NULL); +#else assert(PyThread_get_key_value(autoTLSkey) == NULL); +#endif assert(t->gilstate_counter == 0); _PyGILState_NoteThreadState(t); @@ -731,19 +754,33 @@ void _PyGILState_Fini(void) { +#ifdef __CYGWIN__ + PyThread_tss_delete(&autoTSSkey); +#else PyThread_delete_key(autoTLSkey); autoTLSkey = -1; +#endif autoInterpreterState = NULL; } -/* Reset the TLS key - called by PyOS_AfterFork(). +/* Reset the TLS or the TSS key (cygwin) - 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 TLS or TSS upon fork(), see issue #10517. */ void _PyGILState_Reinit(void) { PyThreadState *tstate = PyGILState_GetThisThreadState(); +#ifdef __CYGWIN__ + 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_tss_set(autoTSSkey, (void *)tstate) != 0) + Py_FatalError("Couldn't create autoTSSkey mapping"); +#else PyThread_delete_key(autoTLSkey); if ((autoTLSkey = PyThread_create_key()) == -1) Py_FatalError("Could not allocate TLS entry"); @@ -752,6 +789,7 @@ * the new key. */ if (tstate && PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) Py_FatalError("Couldn't create autoTLSkey mapping"); +#endif } /* When a thread state is created for a thread by some mechanism other than @@ -762,13 +800,14 @@ static void _PyGILState_NoteThreadState(PyThreadState* tstate) { - /* If autoTLSkey 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 autoTLSkey or 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 local or 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 +819,15 @@ The first thread state created for that given OS level thread will "win", which seems reasonable behaviour. */ +#ifdef __CYGWIN__ + if (PyThread_tss_get(autoTSSkey) == NULL) { + if (PyThread_tss_set(autoTSSkey, (void *)tstate) != 0) + Py_FatalError("Couldn't create autoTSSkey mapping"); +#else if (PyThread_get_key_value(autoTLSkey) == NULL) { if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) Py_FatalError("Couldn't create autoTLSkey mapping"); +#endif } /* PyGILState_Release must not try to delete this thread state. */ @@ -795,7 +840,11 @@ { if (autoInterpreterState == NULL) return NULL; +#ifdef __CYGWIN__ + return (PyThreadState *)PyThread_tss_get(autoTSSkey); +#else return (PyThreadState *)PyThread_get_key_value(autoTLSkey); +#endif } int @@ -806,8 +855,13 @@ if (!_PyGILState_check_enabled) return 1; +#ifdef __CYGWIN__ + if (!PyThread_tss_is_created(autoTSSkey)) + return 1; +#else if (autoTLSkey == -1) return 1; +#endif tstate = GET_TSTATE(); if (tstate == NULL) @@ -827,7 +881,11 @@ called Py_Initialize() and usually PyEval_InitThreads(). */ assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ +#ifdef __CYGWIN__ + tcur = (PyThreadState *)PyThread_tss_get(autoTSSkey); +#else tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); +#endif 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 +917,12 @@ void PyGILState_Release(PyGILState_STATE oldstate) { +#ifdef __CYGWIN__ + PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(autoTSSkey); +#else PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( autoTLSkey); +#endif if (tcur == NULL) Py_FatalError("auto-releasing thread-state, " "but no thread-state for this thread"); diff -r 4243df51fe43 Python/random.c --- a/Python/random.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/random.c Fri Mar 03 22:57:17 2017 -0600 @@ -80,7 +80,11 @@ #else /* !MS_WINDOWS */ #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) +#ifdef __CYGWIN__ +/* on cygwin we must not define PY_GETRANDOM. */ +#else #define PY_GETRANDOM 1 +#endif /* Call getrandom() to get random bytes: @@ -187,7 +191,11 @@ } #elif defined(HAVE_GETENTROPY) +#ifdef __CYGWIN__ +/* on cygwin we must not define PY_GETENTROPY. */ +#else #define PY_GETENTROPY 1 +#endif /* Fill buffer with size pseudo-random bytes generated by getentropy(): diff -r 4243df51fe43 Python/thread.c --- a/Python/thread.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/thread.c Fri Mar 03 22:57:17 2017 -0600 @@ -20,6 +20,9 @@ #include #endif +#ifdef __CYGWIN__ +#include /* necessary for TSS key */ +#endif #include #include "pythread.h" @@ -125,7 +128,8 @@ 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 an existing Python TLS API that has been + deprecated on cygwin. */ /* ------------------------------------------------------------------------ Per-thread data ("key") support. @@ -133,19 +137,30 @@ Use PyThread_create_key() to create a new key. This is typically shared across threads. +On Cygwin use PyThread_tss_create(&thekey) to create a new key instead. + Use PyThread_set_key_value(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. +On Cygwin use PyThread_tss_set(thekey, value) to associate void* value with +thekey in the current thread instead. + Use PyThread_get_key_value(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. +On Cygwin use PyThread_tss_get(thekey) to retrieve the void* value associated +with thekey in the current thread instead. + Use PyThread_delete_key_value(thekey) to forget the current thread's associated value for thekey. PyThread_delete_key(thekey) forgets the values associated with thekey across *all* threads. +On Cygwin use PyThread_tss_delete_value(thekey) to forget the current thread's +associated value for thekey instead. + While some of these functions have error-return values, none set any Python exception. @@ -155,12 +170,13 @@ 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 -next paragraph). +their own locking. This isn't true of PyThread_create_key() or +PyThread_tss_create(), though (see next paragraph). -There's a hidden assumption that PyThread_create_key() 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. +There's a hidden assumption that PyThread_create_key() or 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() or +PyThread_tss_create() are serialized externally. ------------------------------------------------------------------------ */ /* A singly-linked list of struct key objects remembers all the key->value @@ -181,7 +197,9 @@ static struct key *keyhead = NULL; static PyThread_type_lock keymutex = NULL; -static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ +/* PyThread_create_key() or PyThread_tss_create() +hands out nkeys+1 next */ +static int nkeys = 0; /* Internal helper. * If the current thread has a mapping for key, the appropriate struct key* @@ -200,9 +218,9 @@ * 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. - * That could lead to anything, from failing to find a key that exists, to - * segfaults. Now we lock the whole routine. + * record that PyThread_delete_key_value() or 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. */ static struct key * find_key(int set_value, int key, void *value) @@ -225,10 +243,18 @@ * in a tight loop with the lock held. A similar check is done * in pystate.c tstate_delete_common(). */ if (p == prev_p) +#ifdef __CYGWIN__ + Py_FatalError("tss find_key: small circular list(!)"); +#else Py_FatalError("tls find_key: small circular list(!)"); +#endif prev_p = p; if (p->next == keyhead) +#ifdef __CYGWIN__ + Py_FatalError("tss find_key: circular list(!)"); +#else Py_FatalError("tls find_key: circular list(!)"); +#endif } if (!set_value && value == NULL) { assert(p == NULL); @@ -247,6 +273,188 @@ return p; } +#ifdef __CYGWIN__ +/* 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_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(); + key->_key = ++nkeys; + key->_is_initialized = true; + return 0; +} + +/* Forget the associations for key across *all* threads. */ +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; + + struct key *p, **q; + + PyThread_acquire_lock(keymutex, 1); + q = &keyhead; + while ((p = *q) != NULL) { + if (p->key == key->_key) { + *q = p->next; + PyMem_RawFree((void *)p); + /* NB This does *not* free p->value! */ + } + else + q = &p->next; + } + key->_key = -1; + key->_is_initialized = false; + PyThread_release_lock(keymutex); +} + +int +PyThread_tss_set(Py_tss_t key, void *value) +{ + struct key *p = find_key(1, key._key, value); + + if (p == NULL) + return -1; + else + return 0; +} + +/* Retrieve the value associated with key in the current thread, or NULL + * if the current thread doesn't have an association for key. + */ +void * +PyThread_tss_get(Py_tss_t key) +{ + struct key *p = find_key(0, key._key, NULL); + + if (p == NULL) + return NULL; + else + return p->value; +} + +/* Forget the current thread's association for key, if any. */ +void +PyThread_tss_delete_value(Py_tss_t key) +{ + long id = PyThread_get_thread_ident(); + struct key *p, **q; + + PyThread_acquire_lock(keymutex, 1); + q = &keyhead; + while ((p = *q) != NULL) { + if (p->key == key._key && p->id == id) { + *q = p->next; + PyMem_RawFree((void *)p); + /* NB This does *not* free p->value! */ + break; + } + else + q = &p->next; + } + 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_ReInitTSS(void) +{ + long id = PyThread_get_thread_ident(); + struct key *p, **q; + + if (!keymutex) + return; + + /* As with interpreter_lock in PyEval_ReInitThreads() + we just create a new lock without freeing the old one */ + keymutex = PyThread_allocate_lock(); + + /* Delete all keys which do not match the current thread id */ + q = &keyhead; + while ((p = *q) != NULL) { + if (p->id != id) { + *q = p->next; + PyMem_RawFree((void *)p); + /* NB This does *not* free p->value! */ + } + else + q = &p->next; + } +} + +#else /* !CYGWIN */ /* Return 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. @@ -361,6 +569,7 @@ } } +#endif /* CYGWIN */ #endif /* Py_HAVE_NATIVE_TLS */ PyDoc_STRVAR(threadinfo__doc__, diff -r 4243df51fe43 Python/thread_foobar.h --- a/Python/thread_foobar.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/thread_foobar.h Fri Mar 03 22:57:17 2017 -0600 @@ -71,7 +71,7 @@ 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,8 @@ #define Py_HAVE_NATIVE_TLS #ifdef Py_HAVE_NATIVE_TLS +#ifdef __CYGWIN__ +/* Thread Local Storage (TLS) API, DEPRECATED since Python 3.7 */ int PyThread_create_key(void) { @@ -129,4 +131,112 @@ } +/* 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) +{ + +} + +#else /* !CYGWIN */ +int +PyThread_create_key(void) +{ + int result; + return result; +} + +void +PyThread_delete_key(int key) +{ + +} + +int +PyThread_set_key_value(int key, void *value) +{ + int ok; + + /* A failure in this case returns -1 */ + if (!ok) + return -1; + return 0; +} + +void * +PyThread_get_key_value(int key) +{ + void *result; + + return result; +} + +void +PyThread_delete_key_value(int key) +{ + +} + + +void +PyThread_ReInitTLS(void) +{ + +} +#endif /* CYGWIN */ + #endif diff -r 4243df51fe43 Python/thread_nt.h --- a/Python/thread_nt.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/thread_nt.h Fri Mar 03 22:57:17 2017 -0600 @@ -8,6 +8,9 @@ #ifdef HAVE_PROCESS_H #include #endif +#ifdef __CYGWIN__ +#include /* necessary for TSS key */ +#endif /* options */ #ifndef _PY_USE_CV_LOCKS @@ -352,6 +355,131 @@ #define Py_HAVE_NATIVE_TLS #ifdef Py_HAVE_NATIVE_TLS +#ifdef __CYGWIN__ +int +PyThread_create_key(void) +{ + DWORD result = TlsAlloc(); + if (result == TLS_OUT_OF_INDEXES) + return -1; + return (int)result; +} + +void +PyThread_delete_key(int key) +{ + TlsFree(key); +} + +int +PyThread_set_key_value(int key, void *value) +{ + BOOL ok = TlsSetValue(key, value); + return ok ? 0 : -1; +} + +void * +PyThread_get_key_value(int key) +{ + /* because TLS 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); + SetLastError(error); + return result; +} + +void +PyThread_delete_key_value(int key) +{ + /* NULL is used as "key missing", and it is also the default + * given by TlsGetValue() if nothing has been set yet. + */ + 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. + */ +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 TSS functions. And forking isn't supported on Windows either. + */ +void +PyThread_ReInitTSS(void) +{} + +#else /* !CYGWIN */ int PyThread_create_key(void) { @@ -408,5 +536,6 @@ void PyThread_ReInitTLS(void) {} +#endif /* CYGWIN */ #endif diff -r 4243df51fe43 Python/thread_pthread.h --- a/Python/thread_pthread.h Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/thread_pthread.h Fri Mar 03 22:57:17 2017 -0600 @@ -1,6 +1,9 @@ /* Posix threads interface */ +#ifdef __CYGWIN__ +#include /* necessary for TSS key */ +#endif #include #include #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) @@ -602,6 +605,129 @@ #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) #define Py_HAVE_NATIVE_TLS +#ifdef __CYGWIN__ +/* 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 -1L; + if (key > INT_MAX) { + /* Issue #22206: handle integer overflow */ + pthread_key_delete(key); + errno = ENOMEM; + return -1L; + } + return (long)key; +#else + return -1; /* never return valid key value. */ +#endif +} + +void +PyThread_delete_key(long key) +{ +#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT + pthread_key_delete(key); +#endif +} + +void +PyThread_delete_key_value(long key) +{ +#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT + pthread_setspecific(key, NULL); +#endif +} + +int +PyThread_set_key_value(long key, void *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(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) +{} +#else /* !CYGWIN */ int PyThread_create_key(void) @@ -648,3 +774,4 @@ void PyThread_ReInitTLS(void) {} +#endif /* CYGWIN */ diff -r 4243df51fe43 Python/traceback.c --- a/Python/traceback.c Fri Feb 10 14:19:36 2017 +0100 +++ b/Python/traceback.c Fri Mar 03 22:57:17 2017 -0600 @@ -760,7 +760,8 @@ 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 local storage (TLS) or the + thread specific storage (TSS) instead: call PyGILState_GetThisThreadState(). */ current_tstate = PyGILState_GetThisThreadState(); } diff -r 4243df51fe43 configure --- a/configure Fri Feb 10 14:19:36 2017 +0100 +++ b/configure Fri Mar 03 22:57:17 2017 -0600 @@ -9022,6 +9022,75 @@ 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 +"; 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 +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 -r 4243df51fe43 configure.ac --- a/configure.ac Fri Feb 10 14:19:36 2017 +0100 +++ b/configure.ac Fri Mar 03 22:57:17 2017 -0600 @@ -2278,6 +2278,25 @@ #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 ]]) +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_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_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 -r 4243df51fe43 pyconfig.h.in --- a/pyconfig.h.in Fri Feb 10 14:19:36 2017 +0100 +++ b/pyconfig.h.in Fri Mar 03 22:57:17 2017 -0600 @@ -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 -r 4243df51fe43 setup.py --- a/setup.py Fri Feb 10 14:19:36 2017 +0100 +++ b/setup.py Fri Mar 03 22:57:17 2017 -0600 @@ -1242,7 +1242,7 @@ 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 @@ 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 @@ 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 @@ 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,