Skip to content

Enhance Cygwin support #149879

Description

@vstinner

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:

  • Download https://cygwin.com/setup-x86_64.exe
  • Run setup-x86_64.exe : select gcc-core, make, libffi-devel, libssl-devel and zlib-devel packages (I also installed vim, my favorite text editor 😁).
  • Start Cygwin shell (icon on the desktop).
  • Type: git config --global core.autocrlf input -- I had issues with newlines in the ./configure script without that.
  • Run git clone https://github.com/python/cpython/ --depth=1
  • Type: cd cpython
  • Type: ./configure --with-pydebug --cache-file=../configure.cache --without-mimalloc
  • Type: make -j8

mimalloc is disabled because it fails at startup on Cygwin with:

$ PYTHONMALLOC=mimalloc ./python.exe -c pass
mimalloc: warning: cannot decommit OS memory (error: 22 (0x16), address: 0x20000430000, size: 0x1bd0000 bytes)
mimalloc: assertion failed: at "Objects/mimalloc/os.c":444, mi_os_decommit_ex
  assertion: "err == 0"
Aborted

Linked PRs

Activity

  1. StanFromIreland commented on May 15, 2026

    @StanFromIreland
    Member

    I suggest you set up a buildbot, or add it to the CI. Otherwise I fear your work will be broken by future commits :-(

  2. added a commit that references this issue on May 15, 2026
  3. 44 remaining items

  4. added 5 commits that reference this issue on May 26, 2026
  5. vstinner commented on May 26, 2026

    @vstinner
    MemberAuthor

    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.
  6. vstinner commented on May 26, 2026

    @vstinner
    MemberAuthor

    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.
  7. vstinner commented on May 26, 2026

    @vstinner
    MemberAuthor

    I created Enhance Cygwin support topic on discusss.python.org to discuss what should be the next steps for the Cygwin support.

  8. added a commit that references this issue on May 26, 2026
  9. carlo-bramini commented on May 28, 2026

    @carlo-bramini
    Contributor

    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 the fma() 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_FMA inside Modules\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 the fma() 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.
    The fma() 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: SUCCESS
    

    However... 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 support topic.

    EDIT: in my opinion, hypot() function is fine.
    The tests were failing because the function to fail was sqrt() since it is a subset of the pow() function.

  10. vstinner commented on May 28, 2026

    @vstinner
    MemberAuthor

    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.

  11. vstinner commented on May 28, 2026

    @vstinner
    MemberAuthor

    @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.

  12. vstinner commented on Jun 18, 2026

    @vstinner
    MemberAuthor

    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.

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions