Repository navigation
Enhance Cygwin support #149879
Description
Activity
- added sub-issues
on May 15, 2026 - addedtype-featureA feature request or enhancementA feature request or enhancement
on May 15, 2026 I suggest you set up a buildbot, or add it to the CI. Otherwise I fear your work will be broken by future commits :-(
44 remaining items
- added 5 commits that reference this issue
on May 26, 2026 Update: 8 tests are failing.
test_shutil (11 errors, 2 failures) test_c_stack_unwind test_manual_unwind_finds_expected_frames() test_multiprocessing_spawn.test_processes test_wait_result() test_multiprocessing_fork.test_processes test_wait_result() test_zipfile test_extract_dir_backslash() test_capi test_allow_specialization_call() test_concurrent_futures.test_process_pool <test_force_shutdown_workers() hangs> <test_force_shutdown_workers_stops_pool hangs> test_asyncio.test_ssl <test_remote_shutdown_receives_trailing_data_on_slow_socket hangs>The remaining failures are the most complex ones to fix. I'm not sure if it's worth it to fix the last issues.
test_grp also fails, but I have a pending fix: PR gh-150495.
There are also some race conditions.
- test_signal fails sometimes with "env changed" with "OSError: Signal 14 ignored due to race condition".
- test_os.test_os: test_timerfd_select() fails sometimes.
The following test logs warnings:
- test_asyncio.test_subprocess: test_close_dont_kill_finished() leaks a thread.
And there is a Cygwin bug:
- test_threading: test_is_alive_after_fork() fails sometimes with
*** fatal error in forked process - failed to create new win32 semaphore, currentvalue 4294967295, Win32 error 87.
Recent changes:
- Fix venv: copy also the cygpython DLL.
- test_strptime: skip locales when they are known to fail on Cygwin.
- test_math: skip tests on math.fma(), math.hypot() and math.log2() which are known to fail on newlib C library (Cygwin).
- Fix ssl: catch EAGAIN in the getpeername() failure code path.
- Fix test_termios and test_ioctl: skip tests on ENOTTY error.
I created Enhance Cygwin support topic on discusss.python.org to discuss what should be the next steps for the Cygwin support.
- added a commit that references this issue
on May 26, 2026 About:
* test_math: skip tests on math.fma(), math.hypot() and math.log2() which are known to fail on newlib C library (Cygwin).On Cygwin, some of the test on the mathematical functions fail.
You can see this error on screen:0:23:31 load avg: 0.64 [18/40/16] test_math failed (5 errors, 33 failures)followed by a number of lines describing the failed tests.
Actually, the cause of all these errors is inside the implementation of thefma()math function.
This is an "hystorical" bug of Cygwin because NEWLIB provides a very minimalist implementation of this function and, for this reason, it doesn't guarantee the precision and it doesn't even provides a software replacement for this task:https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libm/common/s_fma.c
I have seen that there is a macro called
UNRELIABLE_FMAinsideModules\mathmodule.c.
I tried to activate this macro with a quick hack and the number of failures decreased from 33 to 20.
As you can see, it is still failing elsewhere, the above macro fixed some but not all the issues.
This happens because thefma()is used also for implementing other math functions provided by LIBM.
Affected functions are:fma()pow()log()log2()
So, there is not much that is it could be done here, on the source code of Python.
However, besides the obvious solution of fixing that function inside LIBM, a possible way for fixing this malfunction is using a function from another C library.At the end, Cygwin still runs on top of Windows.
And Windows has its own DLL libraries for providing C functions, including the math ones.
Thefma()is not provided by MSVCRT, but it could be get from UCRT, as well as all other affected math functions.
The UCRT is available on all versions of Windows supported by Cygwin and it can be made available even on Windows XP by installing the Microsoft Visual C++ Redistributable.
So, I did a quick patch for testing and I imported those library functions from UCRT.
As result, all mathematical tests have been executed successfully.
See here my change:diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 6b7fc00..a83d8ea 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -114,6 +114,81 @@ dl_sum(double a, double b) #ifndef UNRELIABLE_FMA +#ifdef __CYGWIN__ + +#define WIN32_LEN_AND_MEAN +#define NOGDI +#include <windows.h> + +#define CRT_NAME "ucrtbase" +#define crt_abi __attribute__((ms_abi)) + +typedef double (crt_abi *crt_fma_t)(double, double, double); +typedef double (crt_abi *crt_pow_t)(double, double); +typedef double (crt_abi *crt_log_t)(double); +typedef double (crt_abi *crt_log2_t)(double); + +static void *crt_get_math_proc_ptr(const char *function_name) +{ + HMODULE crt_handle = GetModuleHandleA(CRT_NAME); + + if (crt_handle) { + return (void *)GetProcAddress(crt_handle, function_name); + } + return NULL; +} + +static double crt_fma(double a, double b, double c) +{ + crt_fma_t crt_fma = (crt_fma_t)crt_get_math_proc_ptr("fma"); + + if (crt_fma) { + return crt_fma(a, b, c); + } + return fma(a, b, c); +} + +static double crt_pow(double a, double b) +{ + crt_pow_t crt_pow = (crt_pow_t)crt_get_math_proc_ptr("pow"); + + if (crt_pow) { + return crt_pow(a, b); + } + return pow(a, b); +} + +static double crt_log(double a) +{ + crt_log_t crt_log = (crt_log_t)crt_get_math_proc_ptr("log"); + + if (crt_log) { + return crt_log(a); + } + return log(a); +} + +static double crt_log2(double a) +{ + crt_log2_t crt_log2 = (crt_log2_t)crt_get_math_proc_ptr("log2"); + + if (crt_log2) { + return crt_log2(a); + } + return log2(a); +} + +#undef fma +#undef pow +#undef log +#undef log2 +#define fma crt_fma +#define pow crt_pow +#define log crt_log +#define log2 crt_log2 + +#endif + static DoubleLength dl_mul(double x, double y) {As you can see, it is just a draft and there are surely better ways for optimizing it, perhaps by loading the pointer to functions only once and falling back to the ones provided by LIBM if they are not found for any reason, or by adding an additional
crt_errno()if an error condition needs to be detected (which is not needed at the time of writing).After running the test, this is the result on screen:
$ ./python.exe -m test -v test_math == CPython 3.16.0a0 (heads/main-dirty:a5cb7c3, May 24 2026, 14:39:47) [GCC 13.4.0] == CYGWIN_NT-10.0-26200-3.6.9-1.x86_64-x86_64-64bit-WindowsPE little-endian == Python build: release shared == cwd: /home/carlo/packages/python/cygwin/build/test_python_worker_1617æ == CPU count: 16 == encodings: locale=UTF-8 FS=utf-8 == resources: all test resources are disabled, use -u option to unskip tests Using random seed: 1958964126 0:00:00 load avg: 3.92 Run 1 test sequentially in a single process 0:00:00 load avg: 3.92 [1/1] test_math test_fma_infinities (test.test_math.FMATests.test_fma_infinities) ... ok test_fma_nan_results (test.test_math.FMATests.test_fma_nan_results) ... ok test_fma_overflow (test.test_math.FMATests.test_fma_overflow) ... ok test_fma_single_round (test.test_math.FMATests.test_fma_single_round) ... ok test_fma_zero_result (test.test_math.FMATests.test_fma_zero_result) ... ok test_random (test.test_math.FMATests.test_random) ... ok test_asymmetry (test.test_math.IsCloseTests.test_asymmetry) ... ok test_decimals (test.test_math.IsCloseTests.test_decimals) ... ok test_eight_decimal_places (test.test_math.IsCloseTests.test_eight_decimal_places) ... ok test_fractions (test.test_math.IsCloseTests.test_fractions) ... ok test_identical (test.test_math.IsCloseTests.test_identical) ... ok test_identical_infinite (test.test_math.IsCloseTests.test_identical_infinite) ... ok test_inf_ninf_nan (test.test_math.IsCloseTests.test_inf_ninf_nan) ... ok test_integers (test.test_math.IsCloseTests.test_integers) ... ok test_near_zero (test.test_math.IsCloseTests.test_near_zero) ... ok test_negative_tolerances (test.test_math.IsCloseTests.test_negative_tolerances) ... ok test_zero_tolerance (test.test_math.IsCloseTests.test_zero_tolerance) ... ok testAcos (test.test_math.MathTests.testAcos) ... ok testAcosh (test.test_math.MathTests.testAcosh) ... ok testAsin (test.test_math.MathTests.testAsin) ... ok testAsinh (test.test_math.MathTests.testAsinh) ... ok testAtan (test.test_math.MathTests.testAtan) ... ok testAtan2 (test.test_math.MathTests.testAtan2) ... ok testAtanh (test.test_math.MathTests.testAtanh) ... ok testCbrt (test.test_math.MathTests.testCbrt) ... ok testCeil (test.test_math.MathTests.testCeil) ... ok testConstants (test.test_math.MathTests.testConstants) ... ok testCopysign (test.test_math.MathTests.testCopysign) ... ok testCos (test.test_math.MathTests.testCos) ... ok testCosh (test.test_math.MathTests.testCosh) ... ok testDegrees (test.test_math.MathTests.testDegrees) ... ok testDist (test.test_math.MathTests.testDist) ... ok testExp (test.test_math.MathTests.testExp) ... ok testExp2 (test.test_math.MathTests.testExp2) ... ok testFabs (test.test_math.MathTests.testFabs) ... ok testFloor (test.test_math.MathTests.testFloor) ... ok testFmod (test.test_math.MathTests.testFmod) ... ok testFrexp (test.test_math.MathTests.testFrexp) ... ok testFsum (test.test_math.MathTests.testFsum) ... ok testGcd (test.test_math.MathTests.testGcd) ... ok testHypot (test.test_math.MathTests.testHypot) ... ok testHypotAccuracy (test.test_math.MathTests.testHypotAccuracy) ... ok testIsfinite (test.test_math.MathTests.testIsfinite) ... ok testIsinf (test.test_math.MathTests.testIsinf) ... ok testIsnan (test.test_math.MathTests.testIsnan) ... ok testIsnormal (test.test_math.MathTests.testIsnormal) ... ok testIssubnormal (test.test_math.MathTests.testIssubnormal) ... ok testLdexp (test.test_math.MathTests.testLdexp) ... ok testLdexp_denormal (test.test_math.MathTests.testLdexp_denormal) ... ok testLog (test.test_math.MathTests.testLog) ... ok testLog10 (test.test_math.MathTests.testLog10) ... ok testLog1p (test.test_math.MathTests.testLog1p) ... ok testLog2 (test.test_math.MathTests.testLog2) ... ok testLog2Exact (test.test_math.MathTests.testLog2Exact) ... ok testModf (test.test_math.MathTests.testModf) ... ok testPow (test.test_math.MathTests.testPow) ... ok testRadians (test.test_math.MathTests.testRadians) ... ok testRemainder (test.test_math.MathTests.testRemainder) ... ok testSin (test.test_math.MathTests.testSin) ... ok testSinh (test.test_math.MathTests.testSinh) ... ok testSqrt (test.test_math.MathTests.testSqrt) ... ok testSumProd (test.test_math.MathTests.testSumProd) ... ok testTan (test.test_math.MathTests.testTan) ... ok testTanh (test.test_math.MathTests.testTanh) ... ok testTanhSign (test.test_math.MathTests.testTanhSign) ... ok test_exception_messages (test.test_math.MathTests.test_exception_messages) ... ok test_exceptions (test.test_math.MathTests.test_exceptions) ... ok test_fmax (test.test_math.MathTests.test_fmax) ... ok test_fmax_nans (test.test_math.MathTests.test_fmax_nans) ... ok test_fmin (test.test_math.MathTests.test_fmin) ... ok test_fmin_nans (test.test_math.MathTests.test_fmin_nans) ... ok test_inf_constant (test.test_math.MathTests.test_inf_constant) ... ok test_input_exceptions (test.test_math.MathTests.test_input_exceptions) ... ok test_issue39871 (test.test_math.MathTests.test_issue39871) ... ok test_lcm (test.test_math.MathTests.test_lcm) ... ok test_log_huge_integer (test.test_math.MathTests.test_log_huge_integer) ... ok test_math_dist_leak (test.test_math.MathTests.test_math_dist_leak) ... ok test_mtestfile (test.test_math.MathTests.test_mtestfile) ... ok test_nan_constant (test.test_math.MathTests.test_nan_constant) ... ok test_nextafter (test.test_math.MathTests.test_nextafter) ... ok test_prod (test.test_math.MathTests.test_prod) ... ok test_signbit (test.test_math.MathTests.test_signbit) ... ok test_sumprod_accuracy (test.test_math.MathTests.test_sumprod_accuracy) ... ok test_sumprod_extended_precision_accuracy (test.test_math.MathTests.test_sumprod_extended_precision_accuracy) ... skipped "resource 'cpu' is not enabled" test_sumprod_stress (test.test_math.MathTests.test_sumprod_stress) ... skipped "resource 'cpu' is not enabled" test_testfile (test.test_math.MathTests.test_testfile) ... ok test_trunc (test.test_math.MathTests.test_trunc) ... ok test_ulp (test.test_math.MathTests.test_ulp) ... ok /home/carlo/packages/python/cpython/Lib/test/mathdata/ieee754.txt Doctest: ieee754.txt ... ok ---------------------------------------------------------------------- Ran 89 tests in 4.454s OK (skipped=2) 0:00:05 load avg: 3.88 [1/1] test_math passed == Tests result: SUCCESS == 1 test OK. Total duration: 5.2 sec Total tests: run=89 skipped=2 Total test files: run=1/1 Result: SUCCESSHowever... in my personal opinion, it would be better to fix LIBM, which would make the problem solved at the roots and it would be nice to have a direct support to FMA3 and FMA4 and a software implementation as fallback.
In that case, it must be also accepted the fact that older versions of Cygwin won't be able to execute the testsuite successfully, but this is quite obvious.I'm providing this report as a reference for the
Enhance Cygwin supporttopic.EDIT: in my opinion,
hypot()function is fine.
The tests were failing because the function to fail wassqrt()since it is a subset of thepow()function.Hum. IMO this math patch is a little too big. Also calling GetModuleHandleA() and GetProcAddress() at each function call is inefficient. I suggest you reporting the issue to newlib bug tracker instead.
@carlo-bramini: So I'm now curious. How are you using Python in Cygwin? Do you use Python to build other packages? Or for something else? You may share your experience at https://discuss.python.org/t/enhance-cygwin-support/107537.
I'm done with Cygwin enhancements. I summarized recent changes on https://discuss.python.org/t/enhance-cygwin-support/107537. I close the issue. For further work, you can open new issues.
Reacted by E. M. Bray
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Cygwin is a free and open-source Unix-like environment and command-line interface for Microsoft Windows. There is an on-going effort to support Cygwin in Python. I create this meta-issue to track other Cygwin sub-issues.
To install Cygwin on Windows and build CPython in Cygwin, you can use these commands:
gcc-core,make,libffi-devel,libssl-develandzlib-develpackages (I also installedvim, my favorite text editor 😁).git config --global core.autocrlf input-- I had issues with newlines in the./configurescript without that.git clone https://github.com/python/cpython/ --depth=1cd cpython./configure --with-pydebug --cache-file=../configure.cache --without-mimallocmake -j8mimalloc is disabled because it fails at startup on Cygwin with:
Linked PRs