mirror of
https://github.com/discourse/discourse.git
synced 2024-12-15 22:42:13 +08:00
405fd9c15d
FIX: Ensure we clean up socket servers.
87 lines
1.6 KiB
Ruby
87 lines
1.6 KiB
Ruby
require 'socket'
|
|
|
|
class SocketServer
|
|
|
|
def initialize(socket_path)
|
|
@socket_path = socket_path
|
|
@server = nil
|
|
end
|
|
|
|
def start(&blk)
|
|
@server = UNIXServer.new(@socket_path)
|
|
@accept_thread = new_accept_thread
|
|
if blk
|
|
@blk = blk
|
|
end
|
|
end
|
|
|
|
def stop
|
|
@server&.close rescue nil
|
|
FileUtils.rm_f(@socket_path)
|
|
@server = nil
|
|
@blk = nil
|
|
end
|
|
|
|
protected
|
|
|
|
def new_accept_thread
|
|
server = @server
|
|
Thread.new do
|
|
begin
|
|
done = false
|
|
while !done
|
|
done = !accept_connection(server)
|
|
end
|
|
ensure
|
|
self.stop
|
|
Rails.logger.info("Cleaned up socket server at #{@socket_path}")
|
|
end
|
|
end
|
|
end
|
|
|
|
def accept_connection(server)
|
|
socket = nil
|
|
begin
|
|
socket = server.accept
|
|
rescue IOError, Errno::EPIPE
|
|
# socket was shut down or something catastrophic like that happened
|
|
return false
|
|
end
|
|
|
|
start = Time.now
|
|
line = ""
|
|
|
|
while Time.now - start < 10
|
|
if IO.select([socket], nil, nil, 10)
|
|
begin
|
|
line << socket.read_nonblock(1000)
|
|
rescue IO::WaitReadable
|
|
sleep 0.001
|
|
end
|
|
end
|
|
break if line.include?("\n")
|
|
end
|
|
|
|
if line.include?("\n")
|
|
socket.write get_response(line.strip)
|
|
end
|
|
|
|
true
|
|
rescue IOError, Errno::EPIPE
|
|
# nothing to do here, case its normal on shutdown
|
|
rescue => e
|
|
Rails.logger.warn("Failed to handle connection in stats socket #{e}:\n#{e.backtrace.join("\n")}")
|
|
ensure
|
|
socket&.close rescue nil
|
|
end
|
|
|
|
def get_response(command)
|
|
if @blk
|
|
@blk.call(command)
|
|
else
|
|
raise "Must be implemented by child"
|
|
end
|
|
end
|
|
|
|
end
|