diff --git a/History.md b/History.md index 1faac2e2..7034333e 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ * Features * Your feature goes here (#Github Number) + * Uses `flush` after writing messages to avoid mutating $stdout and $stderr using `sync=true` ([#2486]) * Fail build if compiling extensions raises warnings on GH Actions ([#1953]) * Add MAKE_WARNINGS_INTO_ERRORS environment variable to toggle whether a build should treat all warnings into errors or not ([#1953]) diff --git a/lib/puma/control_cli.rb b/lib/puma/control_cli.rb index df749ff6..cc874acc 100644 --- a/lib/puma/control_cli.rb +++ b/lib/puma/control_cli.rb @@ -237,6 +237,7 @@ module Puma if sig.nil? @stdout.puts "'#{@command}' not available via pid only" + @stdout.flush unless @stdout.sync return elsif sig.start_with? 'SIG' Process.kill sig, @pid @@ -244,6 +245,7 @@ module Puma begin Process.kill 0, @pid @stdout.puts 'Puma is started' + @stdout.flush unless @stdout.sync rescue Errno::ESRCH raise 'Puma is not running' end diff --git a/lib/puma/error_logger.rb b/lib/puma/error_logger.rb index 7a2bb462..4b1f183a 100644 --- a/lib/puma/error_logger.rb +++ b/lib/puma/error_logger.rb @@ -15,7 +15,6 @@ module Puma def initialize(ioerr) @ioerr = ioerr - @ioerr.sync = true @debug = ENV.key? 'PUMA_DEBUG' end @@ -32,7 +31,7 @@ module Puma # and before all remaining info. # def info(options={}) - ioerr.puts title(options) + log title(options) end # Print occured error details only if @@ -54,7 +53,7 @@ module Puma string_block << request_dump(req) if request_parsed?(req) string_block << error.backtrace if error - ioerr.puts string_block.join("\n") + log string_block.join("\n") end def title(options={}) @@ -93,5 +92,13 @@ module Puma def request_parsed?(req) req && req.env[REQUEST_METHOD] end + + private + + def log(str) + ioerr.puts str + + ioerr.flush unless ioerr.sync + end end end diff --git a/lib/puma/events.rb b/lib/puma/events.rb index 29280075..f96d5538 100644 --- a/lib/puma/events.rb +++ b/lib/puma/events.rb @@ -30,9 +30,6 @@ module Puma @stdout = stdout @stderr = stderr - @stdout.sync = true - @stderr.sync = true - @debug = ENV.key? 'PUMA_DEBUG' @error_logger = ErrorLogger.new(@stderr) @@ -66,6 +63,8 @@ module Puma # def log(str) @stdout.puts format(str) if @stdout.respond_to? :puts + + @stdout.flush unless @stdout.sync rescue Errno::EPIPE end diff --git a/lib/puma/runner.rb b/lib/puma/runner.rb index 615c62d8..a2cbe94e 100644 --- a/lib/puma/runner.rb +++ b/lib/puma/runner.rb @@ -113,8 +113,8 @@ module Puma end STDOUT.reopen stdout, (append ? "a" : "w") - STDOUT.sync = true STDOUT.puts "=== puma startup: #{Time.now} ===" + STDOUT.flush unless STDOUT.sync end if stderr @@ -123,8 +123,8 @@ module Puma end STDERR.reopen stderr, (append ? "a" : "w") - STDERR.sync = true STDERR.puts "=== puma startup: #{Time.now} ===" + STDERR.flush unless STDERR.sync end end diff --git a/test/test_error_logger.rb b/test/test_error_logger.rb index 38aba155..08be9158 100644 --- a/test/test_error_logger.rb +++ b/test/test_error_logger.rb @@ -10,6 +10,14 @@ class TestErrorLogger < Minitest::Test assert_equal STDERR, error_logger.ioerr end + + def test_stdio_respects_sync + error_logger = Puma::ErrorLogger.stdio + + assert_equal STDERR.sync, error_logger.ioerr.sync + assert_equal STDERR, error_logger.ioerr + end + def test_info_with_only_error _, err = capture_io do Puma::ErrorLogger.stdio.info(error: StandardError.new('ready')) diff --git a/test/test_events.rb b/test/test_events.rb index d0da584c..ddd9659c 100644 --- a/test/test_events.rb +++ b/test/test_events.rb @@ -24,6 +24,15 @@ class TestEvents < Minitest::Test assert_equal STDERR, events.stderr end + def test_stdio_respects_sync + events = Puma::Events.stdio + + assert_equal STDOUT.sync, events.stdout.sync + assert_equal STDERR.sync, events.stderr.sync + assert_equal STDOUT, events.stdout + assert_equal STDERR, events.stderr + end + def test_register_callback_with_block res = false