Skip to content

Commit 7c2bc1b

Browse files
committed
Fix Logging.reopen_logs! for ruby 3.4
I think this is probably a bug in ruby 3.4's `IO#reopen`, but it's not a big deal to explicitly copy over the original IO encodings.
1 parent 7b170ba commit 7c2bc1b

File tree

2 files changed

+11
-30
lines changed

2 files changed

+11
-30
lines changed

lib/resque/pool/logging.rb

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,10 @@ def self.reopen_logs!
3636
end
3737

3838
begin
39-
# stdin, stdout, stderr are special. The following dance should
40-
# guarantee there is no window where `fp' is unwritable in MRI
41-
# (or any correct Ruby implementation).
42-
#
43-
# Fwiw, GVL has zero bearing here. This is tricky because of
44-
# the unavoidable existence of stdio FILE * pointers for
45-
# std{in,out,err} in all programs which may use the standard C library
46-
if fp.fileno <= 2
47-
# We do not want to hit fclose(3)->dup(2) window for std{in,out,err}
48-
# MRI will use freopen(3) here internally on std{in,out,err}
49-
fp.reopen(fp.path, "a")
50-
else
51-
# We should not need this workaround, Ruby can be fixed:
52-
# http://bugs.ruby-lang.org/issues/9036
53-
# MRI will not call call fclose(3) or freopen(3) here
54-
# since there's no associated std{in,out,err} FILE * pointer
55-
# This should atomically use dup3(2) (or dup2(2)) syscall
56-
File.open(fp.path, "a") { |tmpfp| fp.reopen(tmpfp) }
57-
end
39+
fp.reopen(fp.path,
40+
mode: "a",
41+
external_encoding: fp.external_encoding,
42+
internal_encoding: fp.internal_encoding)
5843

5944
fp.sync = true
6045
fp.flush # IO#sync=true may not implicitly flush

spec/logging_spec.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
describe Resque::Pool::Logging do
55

66
let(:expect_flags) { File::WRONLY | File::APPEND }
7-
87

98
# Don't pollute the log output
109
before(:all) { $skip_logging = true }
@@ -47,9 +46,8 @@
4746
expect(File.exist?(tmp_path)).to be_truthy
4847
expect(@before).to_not eq(File.stat(tmp_path).inspect)
4948
expect(@fp.stat.inspect).to eq(File.stat(tmp_path).inspect)
50-
pending("ruby 3.4 reopen resets the encoding to nil!") if "3.4.0" <= RUBY_VERSION
51-
expect(@ext).to eq((@fp.external_encoding rescue nil))
52-
expect(@int).to eq((@fp.internal_encoding rescue nil))
49+
expect((@fp.external_encoding rescue nil)).to eq(@ext)
50+
expect((@fp.internal_encoding rescue nil)).to eq(@int)
5351
expect(expect_flags).to eq((expect_flags & @fp.fcntl(Fcntl::F_GETFL)))
5452
expect(@fp.sync).to be_truthy
5553

@@ -71,7 +69,7 @@
7169
Encoding.list.each do |encoding|
7270
File.open(@tmp_path, "a:#{encoding.to_s}") do |fp|
7371
fp.sync = true
74-
expect(encoding).to eq(fp.external_encoding)
72+
expect(fp.external_encoding).to eq(encoding)
7573
expect(fp.internal_encoding).to be_nil
7674
File.unlink(@tmp_path)
7775
expect(File.exist?(@tmp_path)).to be_falsey
@@ -80,8 +78,7 @@
8078
expect(@tmp_path).to eq(fp.path)
8179
expect(File.exist?(@tmp_path)).to be_truthy
8280
expect(fp.stat.inspect).to eq(File.stat(@tmp_path).inspect)
83-
pending("ruby 3.4 reopen resets the encoding to nil!") if "3.4.0" <= RUBY_VERSION
84-
expect(encoding).to eq(fp.external_encoding)
81+
expect(fp.external_encoding).to eq(encoding)
8582
expect(fp.internal_encoding).to be_nil
8683
expect(expect_flags).to eq((expect_flags & fp.fcntl(Fcntl::F_GETFL)))
8784
expect(fp.sync).to be_truthy
@@ -96,7 +93,7 @@
9693
next if ext == int
9794
File.open(@tmp_path, "a:#{ext.to_s}:#{int.to_s}") do |fp|
9895
fp.sync = true
99-
expect(ext).to eq(fp.external_encoding)
96+
expect(fp.external_encoding).to eq(ext)
10097

10198
if ext != Encoding::BINARY
10299
expect(int).to eq(fp.internal_encoding)
@@ -109,11 +106,10 @@
109106
expect(@tmp_path).to eq(fp.path)
110107
expect(File.exist?(@tmp_path)).to be_truthy
111108
expect(fp.stat.inspect).to eq(File.stat(@tmp_path).inspect)
112-
pending("ruby 3.4 reopen resets the encoding to nil!") if "3.4.0" <= RUBY_VERSION
113-
expect(ext).to eq(fp.external_encoding)
109+
expect(fp.external_encoding).to eq(ext)
114110

115111
if ext != Encoding::BINARY
116-
expect(int).to eq(fp.internal_encoding)
112+
expect(fp.internal_encoding).to eq(int)
117113
end
118114

119115
expect(expect_flags).to eq((expect_flags & fp.fcntl(Fcntl::F_GETFL)))

0 commit comments

Comments
 (0)