From 13dc5b88cde691cc4e105de04ebb7804ae633ae6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 15 Jun 2010 23:17:33 +0000 Subject: workaround rbx not reopening logs to stderr/stdout While log reopening worked reliably for newly-created File objects in the unit tests, the $stderr and $stdout handles that get redirected did not get reopened reliably under Rubinius. We work around this by relying on Rubinius internals and directly setting the @path instance variable. This is harmless for MRI and should be harmless for other any other Ruby implementations we'll eventually support. ref: http://github.com/evanphx/rubinius/issues/360 --- lib/unicorn.rb | 7 ++++- lib/unicorn/util.rb | 1 - t/t0006-reopen-logs.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ t/t0006.ru | 13 ++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100755 t/t0006-reopen-logs.sh create mode 100644 t/t0006.ru diff --git a/lib/unicorn.rb b/lib/unicorn.rb index a7b0646..9dcdc29 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -816,7 +816,12 @@ module Unicorn end def redirect_io(io, path) - File.open(path, 'ab') { |fp| io.reopen(fp) } if path + File.open(path, 'ab') do |fp| + io.reopen(fp) + + # workaround for http://github.com/evanphx/rubinius/issues/360 + io.instance_variable_set(:@path, path) if io.path.nil? + end if path io.sync = true end diff --git a/lib/unicorn/util.rb b/lib/unicorn/util.rb index 4e05864..e8c09d0 100644 --- a/lib/unicorn/util.rb +++ b/lib/unicorn/util.rb @@ -22,7 +22,6 @@ module Unicorn ! fp.closed? && fp.sync && - fp.path && fp.path[0] == ?/ && (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags end diff --git a/t/t0006-reopen-logs.sh b/t/t0006-reopen-logs.sh new file mode 100755 index 0000000..430959c --- /dev/null +++ b/t/t0006-reopen-logs.sh @@ -0,0 +1,83 @@ +#!/bin/sh +. ./test-lib.sh + +t_plan 15 "reopen rotated logs" + +t_begin "setup and startup" && { + rtmpfiles curl_out curl_err r_rot + unicorn_setup + unicorn -D t0006.ru -c $unicorn_config + unicorn_wait_start +} + +t_begin "ensure server is responsive" && { + test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err) +} + +t_begin "ensure stderr log is clean" && check_stderr + +t_begin "external log rotation" && { + rm -f $r_rot + mv $r_err $r_rot +} + +t_begin "send reopen log signal (USR1)" && { + kill -USR1 $unicorn_pid +} + +t_begin "wait for rotated log to reappear" && { + nr=60 + while ! test -f $r_err && test $nr -ge 0 + do + sleep 1 + nr=$(( $nr - 1 )) + done +} + +t_begin "ensure server is still responsive" && { + test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err) +} + +t_begin "wait for worker to reopen logs" && { + nr=60 + re="worker=.* done reopening logs" + while ! grep "$re" < $r_err >/dev/null && test $nr -ge 0 + do + sleep 1 + nr=$(( $nr - 1 )) + done +} + +dbgcat r_rot +dbgcat r_err + +t_begin "ensure no errors from curl" && { + test ! -s $curl_err +} + +t_begin "current server stderr is clean" && check_stderr + +t_begin "rotated stderr is clean" && { + check_stderr $r_rot +} + +t_begin "server is now writing logs to new stderr" && { + before_rot=$(wc -c < $r_rot) + before_err=$(wc -c < $r_err) + test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err) + after_rot=$(wc -c < $r_rot) + after_err=$(wc -c < $r_err) + test $after_rot -eq $before_rot + test $after_err -gt $before_err +} + +t_begin "stop server" && { + kill $unicorn_pid +} + +dbgcat r_err + +t_begin "current server stderr is clean" && check_stderr +t_begin "rotated stderr is clean" && check_stderr $r_rot + +t_done diff --git a/t/t0006.ru b/t/t0006.ru new file mode 100644 index 0000000..c39e8f6 --- /dev/null +++ b/t/t0006.ru @@ -0,0 +1,13 @@ +use Rack::ContentLength +use Rack::ContentType, "text/plain" +run lambda { |env| + + # our File objects for stderr/stdout should always have #path + # and be sync=true + ok = $stderr.sync && + $stdout.sync && + String === $stderr.path && + String === $stdout.path + + [ 200, {}, [ "#{ok}\n" ] ] +} -- cgit v1.2.3-24-ge0c7