Skip to content

Commit

Permalink
Avoid leaking file descriptors after Process.fork
Browse files Browse the repository at this point in the history
  • Loading branch information
ntkme committed Dec 4, 2023
1 parent 2676715 commit a2c288d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 15 deletions.
16 changes: 8 additions & 8 deletions lib/sass/compiler/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Compiler
class Connection
def initialize(dispatcher)
@mutex = Mutex.new
@stdin, stdout, stderr, @wait_thread = begin
@stdin, @stdout, @stderr, @wait_thread = begin
Open3.popen3(*CLI::COMMAND, '--embedded', chdir: __dir__)
rescue Errno::ENOENT
require_relative '../elf'
Expand All @@ -26,27 +26,27 @@ def initialize(dispatcher)

Thread.new do
Thread.current.name = 'sass-embedded-process-stdout-poller'
stdout.binmode
@stdout.binmode
loop do
length = Varint.read(stdout)
id = Varint.read(stdout)
proto = stdout.read(length - Varint.length(id))
length = Varint.read(@stdout)
id = Varint.read(@stdout)
proto = @stdout.read(length - Varint.length(id))
dispatcher.receive_proto(id, proto)
rescue IOError, Errno::EBADF, Errno::EPROTO => e
dispatcher.error(e)
break
end
stdout.close
@stdout.close
end

Thread.new do
Thread.current.name = 'sass-embedded-process-stderr-poller'
loop do
warn(stderr.readline, uplevel: 1)
warn(@stderr.readline, uplevel: 1)
rescue IOError, Errno::EBADF
break
end
stderr.close
@stderr.close
end
end

Expand Down
22 changes: 15 additions & 7 deletions lib/sass/embedded.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,26 @@ def current_time

Process.singleton_class.prepend(Module.new do
define_method :_fork do
compiler.instance_eval do
@dispatcher.instance_eval do
@mutex.synchronize do
@dispatcher.instance_eval do
@mutex.synchronize do
@id = 0xffffffff
pid = super()
if pid.zero?
compiler.instance_eval do
@dispatcher.instance_eval do
@mutex.synchronize do
@dispatcher.instance_eval do
@mutex.synchronize do
@id = 0xffffffff
@connection.instance_eval do
@stdin.close
@stdout.close
@stderr.close
end
end
end
end
end
end
end
super()
pid
end
end)

Expand Down

0 comments on commit a2c288d

Please sign in to comment.