Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Keeping Ruby Running on Cygwin

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →
Avatar for fd0 fd0
April 23, 2026

Keeping Ruby Running on Cygwin

Avatar for fd0

fd0

April 23, 2026

More Decks by fd0

Other Decks in Technology

Transcript

  1. ˒ Daisuke Fujimura ˒ Maintainer of the ruby binary package

    on cygwin (Not a Ruby commi tt er) ˒ Interested in software packaging, build systems, and platform engineering About Me 2
  2. ˒ A large collection of GNU and Open Source tools

    which provide functionality similar to a Linux distribution on Windows ˒ A DLL (cygwin1.dll) which provides substantial POSIX API functionality Cygwin is... 5 h tt ps://cygwin.com/
  3. ˒ WSL has taken over many use cases ˒ But

    Cygwin still has demand ˒ Native Windows interop ˒ Legacy work fl ows Cygwin in the WSL Era 6
  4. ˒ O ff icial pre-compiled binary packages ˒ Distributed like

    rpm or deb ˒ Via the Cygwin installer; ruby.exe ready ˒ Maintained by me Ruby on Cygwin 7
  5. ˒ Works like Linux ˒ Unix-style paths (e.g. /home, not

    C:\Users) ˒ Many POSIX APIs work (e.g. Process.fork) ˒ ...and more Di ff erent from Windows Ruby 10
  6. ˒ Each package has a volunteer maintainer ˒ Step away

    → package becomes orphaned ˒ Orphaned = no active maintainer ˒ Ruby went orphaned after 2.6 ˒ Ruby commi tt ers had no Cygwin maintainer either [1] The Orphaned Package 11 [1] h tt ps://github.com/ruby/ruby/blob/master/doc/maintainers.md
  7. ˒ My interests all converge here ˒ Long-time Cygwin user

    ˒ Into language runtimes and libraries ˒ Love Linux packaging (e.g. rpm, deb,...) Motivation: Why I started maintaining Ruby on Cygwin (1) 14
  8. ˒ The outdated Ruby was a real problem ˒ Security

    risk ˒ Missing new features Motivation: Why I started maintaining Ruby on Cygwin (2) 15
  9. ˒ KaigiE ff ect ˒ First a tt ended RubyKaigi

    2018 ˒ Blew my mind; never missed one since Motivation: Why I started maintaining Ruby on Cygwin (3) 16
  10. Release History 17 Version Original Release Cygwin Package Release EOL

    2.6.4 2019-08-28 2019-09-16 2022-04-12 3.2.2 2023-03-30 2023-04-28 2026-03-31 3.4.7 2025-10-07 2025-10-17 TBD h tt ps://cygwin.com/packages/summary/ruby.html
  11. ˒ No handover docs: the repository was the only guide

    ˒ Let's look at what's in there Climbing from 2.6 to 3.2 19
  12. ˒ Cygport: Cygwin's build system ˒ Rules wri tt en

    in bash syntax in a .cygport fi le Repository Tree (1) 20 h tt ps://cygwin.com/cgit/cygwin-packages/ruby/
  13. ˒ Some parts of Ruby assume only major platforms; patches

    make them work correctly on Cygwin Repository Tree (2) 21 h tt ps://cygwin.com/cgit/cygwin-packages/ruby/
  14. ˒ Some patches are sourced from Fedora for reliability and

    license compatibility Repository Tree (3) 22 h tt ps://cygwin.com/cgit/cygwin-packages/ruby/
  15. ˒ Opt out of arch-speci fi c bindir (e.g. /usr/libexec/x86_64-linux/

    bin) Patch Example 23 h tt ps://cygwin.com/cgit/cygwin-packages/ruby/tree/3.4.2-rbinstall-archbindir.patch
  16. ruby.cygport — Metadata 25 ˒ Declared as bash variables: name,

    version, source URLs, patch locations, etc.
  17. ˒ Build steps (compile, install, etc.) are de fi ned

    by overriding bash functions ˒ Ruby uses GNU Autotools; con fi gure options are speci fi ed in src_compile() ruby.cygport — Build Functions 26
  18. Package Layout (1) 📃 ruby.cygport (3.2.2) 📦 ruby (3.2.2) 📦

    ruby-devel (3.2.2) 📦 rubygems (3.4.10) 📦 ruby-rdoc (6.5.0) $ cygport ruby.cygport package 27 X X (3.2.2) (3.2.2)
  19. Package Layout (2) 📃 rubygems.cygport (3.4.10) 📦 rubygems (3.4.10) 📦

    ruby-rdoc (6.5.0) 📃 ruby-rdoc.cygport (6.5.0) $ cygport rubygems.cygport package $ cygport ruby-rdoc.cygport package 28 📃 ruby.cygport (3.2.2) 📦 ruby (3.2.2) $ cygport ruby.cygport package
  20. Package Layout (3) 📦 ruby (3.2.2) /usr/bin/ruby.exe /usr/bin/gem /usr/bin/rdoc :

    📦 rubygems (3.4.10) /usr/bin/gem : 📦 ruby-rdoc (6.5.0) /usr/bin/rdoc : Con fl ict Con fl ict 29
  21. ABI Info Missing (1) 📦 ruby-bcrypt (3.1.20) 📦 ruby (2.6.4)

    📦 ruby (3.2.2) Wants to install Which ABI? ˒ New Ruby → ABI changes → gems must be rebuilt ˒ The installer had no way to know which Ruby ABI each gem was built for ˒ → Unable to resolve dependencies 31
  22. ˒ Hint fi les (generated per package build) → aggregated

    into setup.ini ABI Info Missing (2) 📃 ruby-bcrypt.hint 📃 setup.ini 📃 ruby-devel.hint : 📃 ruby.hint $ mksetupini 32
  23. ˒ O ff icial CI/CD takes it from here ˒

    GitHub Actions: build, upload, update setup.ini, announce ˒ Users get the latest Ruby. happy ending! Ge tt ing It Out the Door 34
  24. ˒ 3.3 never shipped: a SEGV with unknown cause blocked

    the release ˒ gdb investigation, but hard to use e ff ectively ˒ With AI's step-by-step guidance, narrowed down the cause Climbing Again: 3.2 to 3.4 — Debugging with AI 35
  25. ˒ Root cause: SEGV inside pthread, triggered by libssl 3

    ˒ 3.2 was fi ne: linked against libssl 1.1 ˒ Shipped with 3.4.7, after libssl resolved the issue ˒Lesson: sometimes the bug is outside Ruby Climbing Again: 3.2 to 3.4 — Root Cause & Resolution 36
  26. ˒ My own (uno ff icial) CI pipeline ˒ Tracks

    Ruby HEAD ˒ Fix issues upstream, reduce local patches ˒ Led to several upstream PRs ˒ #9269 (#9357), #11952, #14870 Running CI Myself — and What I Found 38
  27. ˒ test_ractor.rb, test_thread.rb → SEGV on Cygwin ˒ Grepping #if

    de fi ned(__CYGWIN__) ˒ native_thread_init_stack() was skipped ˒ Tried removing the exclusion → SEGV was gone ˒ But why? 🤔 ˒ Kept digging to fi nd the reason #9269: Use native_thread_init_stack — Problem 40
  28. ˒ Found commit in 2010 [1] ˒ Incomplete signal stack

    → exclusion was justi fi ed ˒ Cygwin fi xed signal stack in 2015 [2] ˒ Code outlived the reason #9269: Use native_thread_init_stack — Investigation 41 [1] h tt ps://github.com/ruby/ruby/commit/6957c6d9cf0b6a1e211c4b0175bc5474296f2031 [2] h tt ps://github.com/cygwin/cygwin/commit/c8432a01c8401c121940c806a9d868c4adc4cefd
  29. ˒ make test on Cygwin passing again after ~10 years

    ˒ That's win! #9357: Use ubf list 43
  30. ˒ A dangling pointer is a pointer to memory that

    is no longer valid ˒ GCC's -Wdangling-pointer caught one in dln.c ˒ But only on Cygwin #11952: Avoid dangling pointer — Problem: Warning 45
  31. ˒ dladdr(): looks up which library a given address belongs

    to ˒ Fills a Dl_info struct with the result ˒ dli_fname member holds the library fi le path ˒ libname holds dli_fname... #11952: Avoid dangling pointer — Problem: The Code 46
  32. #11952: Avoid dangling pointer — Investigation: Type Di ff erence

    47 Linux [1] Cygwin [2] [1] h tt ps://sourceware.org/git/?p=glibc.git;a=blob;f=dlfcn/dlfcn.h [2] h tt ps://github.com/cygwin/cygwin/blob/main/winsup/cygwin/include/dlfcn.h
  33. ˒ Why the type di ff erence? ˒ dladdr() standardized

    in POSIX Issue 8 (2024) ˒ Cygwin: 2017 [1] ˒ Each platform de fi ned types independently #11952: Avoid dangling pointer — Investigation: Background 48 [1] h tt ps://github.com/cygwin/cygwin/commit/c8432a01c8401c121940c806a9d868c4adc4cefd
  34. ˒ libname is only used in error messages; skipping is

    su ff icient #11952: Avoid dangling pointer — Fix 49
  35. ˒ Tried namespace (box) locally ˒ Native extension .so →

    LoadError #14870: Fix extension fi le permissions in namespace feature — Problem 51
  36. ˒ fwrite copy → dlopen #14870: Fix extension fi le

    permissions in namespace feature — Investigation: Copy 52
  37. ˒ Cygwin: copied .so permissions come from Windows ACL ˒

    The executable bit was not set on the copy #14870: Fix extension fi le permissions in namespace feature — Investigation: Permission 53 -rwxr-xr-x openssl.so -rw-r--r-- openssl.so Copy by fwrite
  38. ˒ dlopen internally calls Windows LoadLibraryW ˒ No Executable in

    ACL → ERROR_ACCESS_DENIED ˒ Not o ff icially documented, but widely known behavior #14870: Fix extension fi le permissions in namespace feature — Investigation: Implementation 54
  39. ˒ Preserve permissions after fwrite copy #14870: Fix extension fi

    le permissions in namespace feature — Fix 55
  40. ˒ My CI caught a compile failure on Cygwin ˒

    -municode (MinGW-w64-only) accidentally applied to Cygwin ˒ Fixed by #12015 Cygwin Joins the O ff icial CI Matrix (1) 57
  41. ˒ To prevent this class of breakage from landing again

    ˒ Now every commit is veri fi ed to build on Cygwin Cygwin Joins the O ff icial CI Matrix (2) 58
  42. ˒ Upgraded Ruby on Cygwin from 2.6 to 3.4 ˒

    Deepened understanding of the packaging system ˒ Encountered a new debugging experience ˒ A dependency-blocked release tackled with AI Looking Back — Packaging Journey 60
  43. ˒ Niche bugs that only surface on Cygwin ˒ Hard

    to see without downstream involvement ˒ Cygwin is now in the o ff icial CI matrix Looking Back — Upstream Contributions 61
  44. ˒ All of this contributes to Ruby's "Highly Portable" goal

    ˒ Covering underserved platforms helps grow the Ruby community Looking Forward 62