Skip to content

Commit 665d812

Browse files
committed
Use a more gentle shutdown for SmallHTTPServer
* By opening a socket and send a special close message. * Socket#close is very difficult to get right, notably Socket#accept does multiple blocking system calls, and if close(2) is done in the middle it might result in EBADF or worse, doing the call on an unrelated IO.
1 parent 596c3e1 commit 665d812

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

spec/ruby/library/net/http/http/fixtures/http_server.rb

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,23 @@ def printf(*args) end
1111
class SmallHTTPServer
1212
def initialize(bind_address)
1313
@server = TCPServer.new(bind_address, 0)
14-
@running = Mutex.new
1514
@thread = Thread.new {
1615
Thread.current.abort_on_exception = true
1716
listen
1817
}
1918
end
2019

20+
def ip
21+
@server.addr[3]
22+
end
23+
2124
def port
2225
@server.addr[1]
2326
end
2427

2528
def listen
26-
loop do
27-
begin
28-
client = @server.accept
29-
rescue IOError => e
30-
if @running.locked? # close
31-
break
32-
else
33-
raise e
34-
end
35-
end
36-
29+
until @server.closed?
30+
client = @server.accept
3731
handle_client(client)
3832
end
3933
end
@@ -43,6 +37,10 @@ def handle_client(client)
4337
until client.closed?
4438
request = client.gets("\r\n\r\n")
4539
break unless request
40+
if request == "CLOSE"
41+
@server.close
42+
break
43+
end
4644
handle_request(client, request)
4745
end
4846
ensure
@@ -95,8 +93,9 @@ def reply(client, body, request_method)
9593
end
9694

9795
def close
98-
@running.lock
99-
@server.close
96+
TCPSocket.open(ip, port) do |socket|
97+
socket.write "CLOSE"
98+
end
10099
@thread.join
101100
end
102101
end

0 commit comments

Comments
 (0)