forked from pingcap/discourse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsocket_server.rb
88 lines (74 loc) · 1.63 KB
/
socket_server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# frozen_string_literal: true
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
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 #{e}:\n#{e.backtrace.join("\n")}")
ensure
socket&.close
end
def get_response(command)
if @blk
@blk.call(command)
else
raise "Must be implemented by child"
end
end
end