Skip to content

Build: Support Ruby 4 - #1

Merged
elohmeier merged 7 commits into
masterfrom
ruby-4-compat
Aug 1, 2026
Merged

Build: Support Ruby 4#1
elohmeier merged 7 commits into
masterfrom
ruby-4-compat

Conversation

@elohmeier

Copy link
Copy Markdown
Owner

Summary

  • incorporate the Ruby compatibility fixes from upstream PRs #294, #313, and #322
  • declare the extracted base64 and drb runtime dependencies and a maintained Ruby 3.2+ development toolchain
  • make the gem buildable from a clean checkout
  • add regression coverage for BatchProcessor and ReportServlet plus a live daemon/web smoke test
  • test Ruby 3.2, 3.3, 3.4, and 4.0 in GitHub Actions

Validation

  • 111 unit tests, 262,170 assertions
  • 70 specification examples
  • syntax check and schedule of a sample project
  • 20 tutorial reports generated with two worker processes
  • live daemon, web server, and report request
  • packaged taskjuggler-3.8.4 gem inspected successfully
  • Ruby matrix passes on all four versions

jarkad and others added 7 commits August 1, 2026 11:03
To reproduce the issue, launch the web server with no configuration, add a project (its contents don't matter), and open http://127.0.0.1:8080/taskjuggler .

<details>
<summary><code>tj3webd</code> output</summary>

```
$ tj3webd -d --debug
TaskJuggler v3.8.4 - A Project Management Software

Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020
              by Chris Schlaeger <cs@taskjuggler.org>

This program is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published by the
Free Software Foundation.

[2025-11-27 20:30:10] INFO  WEBrick 1.9.2
[2025-11-27 20:30:10] INFO  ruby 3.4.1 (2024-12-25) [aarch64-linux-android]
[2025-11-27 20:30:10] INFO  WEBrick::HTTPServer#start: pid=7462 port=8080
127.0.0.1 - - [27/Nov/2025:20:30:36 CET] "GET /taskjuggler HTTP/1.1" 200 422
- -> /taskjuggler
Exception 'WEBrick::HTTPStatus::EOFError' at /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/webrick-1.9.2/lib/webrick/httpserver.rb:82 - WEBrick::HTTPStatus::EOFError
Exception 'FrozenError' at /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/daemon/ReportServlet.rb:191 - can't modify frozen String: "== Welcome to the TaskJuggler Project Server ==\n----\n"
Error: Cannot serve GET request: GET /taskjuggler HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Android 10; Mobile; rv:133.0) Gecko/133.0 Firefox/133.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US
Accept-Encoding: gzip, deflate, br, zstd
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Priority: u=0, i

can't modify frozen String: "== Welcome to the TaskJuggler Project Server ==\n----\n"
127.0.0.1 - - [27/Nov/2025:20:40:36 CET] "GET /taskjuggler HTTP/1.1" 412 563
- -> /taskjuggler
[2025-11-27 20:40:36] ERROR SystemExit: exit
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/MessageHandler.rb:298:in 'Kernel#exit'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/MessageHandler.rb:298:in 'TaskJuggler::MessageHandlerInstance#addMessage'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/MessageHandler.rb:197:in 'TaskJuggler::MessageHandlerInstance#error'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/daemon/ReportServlet.rb:240:in 'TaskJuggler::ReportServlet#error'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/taskjuggler-3.8.4/lib/taskjuggler/daemon/ReportServlet.rb:62:in 'TaskJuggler::ReportServlet#do_GET'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/webrick-1.9.2/lib/webrick/httpservlet/abstract.rb:105:in 'WEBrick::HTTPServlet::AbstractServlet#service'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/webrick-1.9.2/lib/webrick/httpserver.rb:140:in 'WEBrick::HTTPServer#service'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/webrick-1.9.2/lib/webrick/httpserver.rb:96:in 'WEBrick::HTTPServer#run'
        /data/data/com.termux/files/usr/lib/ruby/gems/3.4.0/gems/webrick-1.9.2/lib/webrick/server.rb:309:in 'block in WEBrick::GenericServer#start_thread'
```

</details>
In Ruby 3.4+, IO#reopen no longer accepts StringIO objects as an
argument. It expects a String (file path) instead. This caused tj3d
and tj3webd to fail with:

  Fatal: no implicit conversion of StringIO into String

Change .reopen(StringIO.new) back to
.reopen('/dev/null', 'a') which works on all Ruby versions.

Reported-by: GitHub issue taskjuggler#303

Assisted-by: opencode/qwen3.6-plus
Signed-off-by: Ankur Sinha (Ankur Sinha Gmail) <sanjay.ankur@gmail.com>
In Ruby 4.0+, StringIO.new('') unexpectedly creates a read-only buffer
in the web server context. This caused report generation via the web
interface to fail with:

  IOError: not opened for writing

Use StringIO.new without arguments instead, which creates a writable
buffer. Also add a missing return statement after the connect error to
prevent further execution.

Investigation:
- StringIO.new('') works correctly in standalone Ruby scripts
- StringIO.new('') works correctly in a forked daemon process
- StringIO.new('') works correctly in a standalone WEBrick handler
- The bug only manifests in the full TaskJuggler web server process,
  which involves multiple forks, DRb servers, and the complete
  TaskJuggler module stack loaded together
- It is unclear why StringIO.new('') behaves differently in this
  context. Root cause not yet identified.

Reported-by: GitHub issue taskjuggler#303

Assisted-by: opencode/qwen3.6-plus
Signed-off-by: Ankur Sinha (Ankur Sinha Gmail) <sanjay.ankur@gmail.com>
@elohmeier
elohmeier merged commit d69fdb9 into master Aug 1, 2026
8 checks passed
@elohmeier
elohmeier deleted the ruby-4-compat branch August 1, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants