webrick 1.3.1 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of webrick might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/webrick.rb +6 -6
- data/lib/webrick/accesslog.rb +9 -1
- data/lib/webrick/cgi.rb +58 -5
- data/lib/webrick/compat.rb +2 -1
- data/lib/webrick/config.rb +47 -10
- data/lib/webrick/cookie.rb +69 -7
- data/lib/webrick/htmlutils.rb +4 -2
- data/lib/webrick/httpauth.rb +6 -5
- data/lib/webrick/httpauth/authenticator.rb +13 -8
- data/lib/webrick/httpauth/basicauth.rb +16 -8
- data/lib/webrick/httpauth/digestauth.rb +35 -32
- data/lib/webrick/httpauth/htdigest.rb +12 -8
- data/lib/webrick/httpauth/htgroup.rb +10 -6
- data/lib/webrick/httpauth/htpasswd.rb +46 -9
- data/lib/webrick/httpauth/userdb.rb +1 -0
- data/lib/webrick/httpproxy.rb +93 -48
- data/lib/webrick/httprequest.rb +192 -27
- data/lib/webrick/httpresponse.rb +182 -62
- data/lib/webrick/https.rb +90 -2
- data/lib/webrick/httpserver.rb +45 -15
- data/lib/webrick/httpservlet.rb +6 -5
- data/lib/webrick/httpservlet/abstract.rb +5 -6
- data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
- data/lib/webrick/httpservlet/cgihandler.rb +22 -10
- data/lib/webrick/httpservlet/erbhandler.rb +4 -3
- data/lib/webrick/httpservlet/filehandler.rb +136 -65
- data/lib/webrick/httpservlet/prochandler.rb +15 -1
- data/lib/webrick/httpstatus.rb +24 -14
- data/lib/webrick/httputils.rb +132 -13
- data/lib/webrick/httpversion.rb +28 -1
- data/lib/webrick/log.rb +25 -5
- data/lib/webrick/server.rb +234 -74
- data/lib/webrick/ssl.rb +100 -12
- data/lib/webrick/utils.rb +98 -69
- data/lib/webrick/version.rb +6 -1
- metadata +66 -72
- data/README.txt +0 -21
- data/sample/webrick/demo-app.rb +0 -66
- data/sample/webrick/demo-multipart.cgi +0 -12
- data/sample/webrick/demo-servlet.rb +0 -6
- data/sample/webrick/demo-urlencoded.cgi +0 -12
- data/sample/webrick/hello.cgi +0 -11
- data/sample/webrick/hello.rb +0 -8
- data/sample/webrick/httpd.rb +0 -23
- data/sample/webrick/httpproxy.rb +0 -25
- data/sample/webrick/httpsd.rb +0 -33
- data/test/openssl/utils.rb +0 -313
- data/test/ruby/envutil.rb +0 -208
- data/test/webrick/test_cgi.rb +0 -134
- data/test/webrick/test_cookie.rb +0 -131
- data/test/webrick/test_filehandler.rb +0 -285
- data/test/webrick/test_httpauth.rb +0 -167
- data/test/webrick/test_httpproxy.rb +0 -282
- data/test/webrick/test_httprequest.rb +0 -411
- data/test/webrick/test_httpresponse.rb +0 -49
- data/test/webrick/test_httpserver.rb +0 -305
- data/test/webrick/test_httputils.rb +0 -96
- data/test/webrick/test_httpversion.rb +0 -40
- data/test/webrick/test_server.rb +0 -67
- data/test/webrick/test_utils.rb +0 -64
- data/test/webrick/utils.rb +0 -58
- data/test/webrick/webrick.cgi +0 -36
- data/test/webrick/webrick_long_filename.cgi +0 -36
data/lib/webrick/httpversion.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#--
|
2
3
|
# HTTPVersion.rb -- presentation of HTTP version
|
3
4
|
#
|
@@ -8,15 +9,33 @@
|
|
8
9
|
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
|
9
10
|
|
10
11
|
module WEBrick
|
12
|
+
|
13
|
+
##
|
14
|
+
# Represents an HTTP protocol version
|
15
|
+
|
11
16
|
class HTTPVersion
|
12
17
|
include Comparable
|
13
18
|
|
14
|
-
|
19
|
+
##
|
20
|
+
# The major protocol version number
|
21
|
+
|
22
|
+
attr_accessor :major
|
23
|
+
|
24
|
+
##
|
25
|
+
# The minor protocol version number
|
26
|
+
|
27
|
+
attr_accessor :minor
|
28
|
+
|
29
|
+
##
|
30
|
+
# Converts +version+ into an HTTPVersion
|
15
31
|
|
16
32
|
def self.convert(version)
|
17
33
|
version.is_a?(self) ? version : new(version)
|
18
34
|
end
|
19
35
|
|
36
|
+
##
|
37
|
+
# Creates a new HTTPVersion from +version+.
|
38
|
+
|
20
39
|
def initialize(version)
|
21
40
|
case version
|
22
41
|
when HTTPVersion
|
@@ -32,6 +51,10 @@ module WEBrick
|
|
32
51
|
end
|
33
52
|
end
|
34
53
|
|
54
|
+
##
|
55
|
+
# Compares this version with +other+ according to the HTTP specification
|
56
|
+
# rules.
|
57
|
+
|
35
58
|
def <=>(other)
|
36
59
|
unless other.is_a?(self.class)
|
37
60
|
other = self.class.new(other)
|
@@ -42,6 +65,10 @@ module WEBrick
|
|
42
65
|
return ret
|
43
66
|
end
|
44
67
|
|
68
|
+
##
|
69
|
+
# The HTTP version as show in the HTTP request and response. For example,
|
70
|
+
# "1.1"
|
71
|
+
|
45
72
|
def to_s
|
46
73
|
format("%d.%d", @major, @minor)
|
47
74
|
end
|
data/lib/webrick/log.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#--
|
2
3
|
# log.rb -- Log Class
|
3
4
|
#
|
@@ -14,8 +15,27 @@ module WEBrick
|
|
14
15
|
# A generic logging class
|
15
16
|
|
16
17
|
class BasicLog
|
17
|
-
|
18
|
-
|
18
|
+
|
19
|
+
# Fatal log level which indicates a server crash
|
20
|
+
|
21
|
+
FATAL = 1
|
22
|
+
|
23
|
+
# Error log level which indicates a recoverable error
|
24
|
+
|
25
|
+
ERROR = 2
|
26
|
+
|
27
|
+
# Warning log level which indicates a possible problem
|
28
|
+
|
29
|
+
WARN = 3
|
30
|
+
|
31
|
+
# Information log level which indicates possibly useful information
|
32
|
+
|
33
|
+
INFO = 4
|
34
|
+
|
35
|
+
# Debugging error level for messages used in server development or
|
36
|
+
# debugging
|
37
|
+
|
38
|
+
DEBUG = 5
|
19
39
|
|
20
40
|
# log-level, messages above this level will be logged
|
21
41
|
attr_accessor :level
|
@@ -31,7 +51,7 @@ module WEBrick
|
|
31
51
|
@level = level || INFO
|
32
52
|
case log_file
|
33
53
|
when String
|
34
|
-
@log = open(log_file, "a+")
|
54
|
+
@log = File.open(log_file, "a+")
|
35
55
|
@log.sync = true
|
36
56
|
@opened = true
|
37
57
|
when NilClass
|
@@ -98,10 +118,10 @@ module WEBrick
|
|
98
118
|
# * Otherwise it will return +arg+.inspect.
|
99
119
|
def format(arg)
|
100
120
|
if arg.is_a?(Exception)
|
101
|
-
"#{arg.class}: #{arg.message}\n\t" <<
|
121
|
+
"#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" <<
|
102
122
|
arg.backtrace.join("\n\t") << "\n"
|
103
123
|
elsif arg.respond_to?(:to_str)
|
104
|
-
arg.to_str
|
124
|
+
AccessLog.escape(arg.to_str)
|
105
125
|
else
|
106
126
|
arg.inspect
|
107
127
|
end
|
data/lib/webrick/server.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# server.rb -- GenericServer Class
|
3
4
|
#
|
@@ -8,16 +9,25 @@
|
|
8
9
|
#
|
9
10
|
# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
|
10
11
|
|
11
|
-
require 'thread'
|
12
12
|
require 'socket'
|
13
|
-
|
14
|
-
|
13
|
+
require_relative 'config'
|
14
|
+
require_relative 'log'
|
15
15
|
|
16
16
|
module WEBrick
|
17
17
|
|
18
|
+
##
|
19
|
+
# Server error exception
|
20
|
+
|
18
21
|
class ServerError < StandardError; end
|
19
22
|
|
23
|
+
##
|
24
|
+
# Base server class
|
25
|
+
|
20
26
|
class SimpleServer
|
27
|
+
|
28
|
+
##
|
29
|
+
# A SimpleServer only yields when you start it
|
30
|
+
|
21
31
|
def SimpleServer.start
|
22
32
|
yield
|
23
33
|
end
|
@@ -33,20 +43,47 @@ module WEBrick
|
|
33
43
|
# block, if given.
|
34
44
|
|
35
45
|
def Daemon.start
|
36
|
-
|
37
|
-
|
38
|
-
exit!(0) if fork
|
39
|
-
Dir::chdir("/")
|
40
|
-
File::umask(0)
|
41
|
-
STDIN.reopen("/dev/null")
|
42
|
-
STDOUT.reopen("/dev/null", "w")
|
43
|
-
STDERR.reopen("/dev/null", "w")
|
46
|
+
Process.daemon
|
47
|
+
File.umask(0)
|
44
48
|
yield if block_given?
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
52
|
+
##
|
53
|
+
# Base TCP server class. You must subclass GenericServer and provide a #run
|
54
|
+
# method.
|
55
|
+
|
48
56
|
class GenericServer
|
49
|
-
|
57
|
+
|
58
|
+
##
|
59
|
+
# The server status. One of :Stop, :Running or :Shutdown
|
60
|
+
|
61
|
+
attr_reader :status
|
62
|
+
|
63
|
+
##
|
64
|
+
# The server configuration
|
65
|
+
|
66
|
+
attr_reader :config
|
67
|
+
|
68
|
+
##
|
69
|
+
# The server logger. This is independent from the HTTP access log.
|
70
|
+
|
71
|
+
attr_reader :logger
|
72
|
+
|
73
|
+
##
|
74
|
+
# Tokens control the number of outstanding clients. The
|
75
|
+
# <code>:MaxClients</code> configuration sets this.
|
76
|
+
|
77
|
+
attr_reader :tokens
|
78
|
+
|
79
|
+
##
|
80
|
+
# Sockets listening for connections.
|
81
|
+
|
82
|
+
attr_reader :listeners
|
83
|
+
|
84
|
+
##
|
85
|
+
# Creates a new generic server from +config+. The default configuration
|
86
|
+
# comes from +default+.
|
50
87
|
|
51
88
|
def initialize(config={}, default=Config::General)
|
52
89
|
@config = default.dup.update(config)
|
@@ -54,7 +91,7 @@ module WEBrick
|
|
54
91
|
@config[:Logger] ||= Log::new
|
55
92
|
@logger = @config[:Logger]
|
56
93
|
|
57
|
-
@tokens = SizedQueue.new(@config[:MaxClients])
|
94
|
+
@tokens = Thread::SizedQueue.new(@config[:MaxClients])
|
58
95
|
@config[:MaxClients].times{ @tokens.push(nil) }
|
59
96
|
|
60
97
|
webrickv = WEBrick::VERSION
|
@@ -63,9 +100,10 @@ module WEBrick
|
|
63
100
|
@logger.info("ruby #{rubyv}")
|
64
101
|
|
65
102
|
@listeners = []
|
103
|
+
@shutdown_pipe = nil
|
66
104
|
unless @config[:DoNotListen]
|
67
105
|
if @config[:Listen]
|
68
|
-
warn(":Listen option is deprecated; use GenericServer#listen")
|
106
|
+
warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
|
69
107
|
end
|
70
108
|
listen(@config[:BindAddress], @config[:Port])
|
71
109
|
if @config[:Port] == 0
|
@@ -74,108 +112,176 @@ module WEBrick
|
|
74
112
|
end
|
75
113
|
end
|
76
114
|
|
115
|
+
##
|
116
|
+
# Retrieves +key+ from the configuration
|
117
|
+
|
77
118
|
def [](key)
|
78
119
|
@config[key]
|
79
120
|
end
|
80
121
|
|
122
|
+
##
|
123
|
+
# Adds listeners from +address+ and +port+ to the server. See
|
124
|
+
# WEBrick::Utils::create_listeners for details.
|
125
|
+
|
81
126
|
def listen(address, port)
|
82
|
-
@listeners += Utils::create_listeners(address, port
|
127
|
+
@listeners += Utils::create_listeners(address, port)
|
83
128
|
end
|
84
129
|
|
130
|
+
##
|
131
|
+
# Starts the server and runs the +block+ for each connection. This method
|
132
|
+
# does not return until the server is stopped from a signal handler or
|
133
|
+
# another thread using #stop or #shutdown.
|
134
|
+
#
|
135
|
+
# If the block raises a subclass of StandardError the exception is logged
|
136
|
+
# and ignored. If an IOError or Errno::EBADF exception is raised the
|
137
|
+
# exception is ignored. If an Exception subclass is raised the exception
|
138
|
+
# is logged and re-raised which stops the server.
|
139
|
+
#
|
140
|
+
# To completely shut down a server call #shutdown from ensure:
|
141
|
+
#
|
142
|
+
# server = WEBrick::GenericServer.new
|
143
|
+
# # or WEBrick::HTTPServer.new
|
144
|
+
#
|
145
|
+
# begin
|
146
|
+
# server.start
|
147
|
+
# ensure
|
148
|
+
# server.shutdown
|
149
|
+
# end
|
150
|
+
|
85
151
|
def start(&block)
|
86
152
|
raise ServerError, "already started." if @status != :Stop
|
87
153
|
server_type = @config[:ServerType] || SimpleServer
|
88
154
|
|
155
|
+
setup_shutdown_pipe
|
156
|
+
|
89
157
|
server_type.start{
|
90
158
|
@logger.info \
|
91
159
|
"#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
|
160
|
+
@status = :Running
|
92
161
|
call_callback(:StartCallback)
|
93
162
|
|
163
|
+
shutdown_pipe = @shutdown_pipe
|
164
|
+
|
94
165
|
thgroup = ThreadGroup.new
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
svrs[
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
else
|
107
|
-
@tokens.push(nil)
|
166
|
+
begin
|
167
|
+
while @status == :Running
|
168
|
+
begin
|
169
|
+
sp = shutdown_pipe[0]
|
170
|
+
if svrs = IO.select([sp, *@listeners])
|
171
|
+
if svrs[0].include? sp
|
172
|
+
# swallow shutdown pipe
|
173
|
+
buf = String.new
|
174
|
+
nil while String ===
|
175
|
+
sp.read_nonblock([sp.nread, 8].max, buf, exception: false)
|
176
|
+
break
|
108
177
|
end
|
109
|
-
|
178
|
+
svrs[0].each{|svr|
|
179
|
+
@tokens.pop # blocks while no token is there.
|
180
|
+
if sock = accept_client(svr)
|
181
|
+
unless config[:DoNotReverseLookup].nil?
|
182
|
+
sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup]
|
183
|
+
end
|
184
|
+
th = start_thread(sock, &block)
|
185
|
+
th[:WEBrickThread] = true
|
186
|
+
thgroup.add(th)
|
187
|
+
else
|
188
|
+
@tokens.push(nil)
|
189
|
+
end
|
190
|
+
}
|
191
|
+
end
|
192
|
+
rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex
|
193
|
+
# if the listening socket was closed in GenericServer#shutdown,
|
194
|
+
# IO::select raise it.
|
195
|
+
rescue StandardError => ex
|
196
|
+
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
197
|
+
@logger.error msg
|
198
|
+
rescue Exception => ex
|
199
|
+
@logger.fatal ex
|
200
|
+
raise
|
110
201
|
end
|
111
|
-
rescue Errno::EBADF, IOError => ex
|
112
|
-
# if the listening socket was closed in GenericServer#shutdown,
|
113
|
-
# IO::select raise it.
|
114
|
-
rescue Exception => ex
|
115
|
-
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
116
|
-
@logger.error msg
|
117
202
|
end
|
203
|
+
ensure
|
204
|
+
cleanup_shutdown_pipe(shutdown_pipe)
|
205
|
+
cleanup_listener
|
206
|
+
@status = :Shutdown
|
207
|
+
@logger.info "going to shutdown ..."
|
208
|
+
thgroup.list.each{|th| th.join if th[:WEBrickThread] }
|
209
|
+
call_callback(:StopCallback)
|
210
|
+
@logger.info "#{self.class}#start done."
|
211
|
+
@status = :Stop
|
118
212
|
end
|
119
|
-
|
120
|
-
@logger.info "going to shutdown ..."
|
121
|
-
thgroup.list.each{|th| th.join if th[:WEBrickThread] }
|
122
|
-
call_callback(:StopCallback)
|
123
|
-
@logger.info "#{self.class}#start done."
|
124
|
-
@status = :Stop
|
125
213
|
}
|
126
214
|
end
|
127
215
|
|
216
|
+
##
|
217
|
+
# Stops the server from accepting new connections.
|
218
|
+
|
128
219
|
def stop
|
129
220
|
if @status == :Running
|
130
221
|
@status = :Shutdown
|
131
222
|
end
|
223
|
+
|
224
|
+
alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
|
132
225
|
end
|
133
226
|
|
227
|
+
##
|
228
|
+
# Shuts down the server and all listening sockets. New listeners must be
|
229
|
+
# provided to restart the server.
|
230
|
+
|
134
231
|
def shutdown
|
135
232
|
stop
|
136
|
-
|
137
|
-
|
138
|
-
addr = s.addr
|
139
|
-
@logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
|
140
|
-
end
|
141
|
-
begin
|
142
|
-
s.shutdown
|
143
|
-
rescue Errno::ENOTCONN
|
144
|
-
# when `Errno::ENOTCONN: Socket is not connected' on some platforms,
|
145
|
-
# call #close instead of #shutdown.
|
146
|
-
# (ignore @config[:ShutdownSocketWithoutClose])
|
147
|
-
s.close
|
148
|
-
else
|
149
|
-
unless @config[:ShutdownSocketWithoutClose]
|
150
|
-
s.close
|
151
|
-
end
|
152
|
-
end
|
153
|
-
}
|
154
|
-
@listeners.clear
|
233
|
+
|
234
|
+
alarm_shutdown_pipe(&:close)
|
155
235
|
end
|
156
236
|
|
237
|
+
##
|
238
|
+
# You must subclass GenericServer and implement \#run which accepts a TCP
|
239
|
+
# client socket
|
240
|
+
|
157
241
|
def run(sock)
|
158
242
|
@logger.fatal "run() must be provided by user."
|
159
243
|
end
|
160
244
|
|
161
245
|
private
|
162
246
|
|
247
|
+
# :stopdoc:
|
248
|
+
|
249
|
+
##
|
250
|
+
# Accepts a TCP client socket from the TCP server socket +svr+ and returns
|
251
|
+
# the client socket.
|
252
|
+
|
163
253
|
def accept_client(svr)
|
164
|
-
sock =
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
254
|
+
case sock = svr.to_io.accept_nonblock(exception: false)
|
255
|
+
when :wait_readable
|
256
|
+
nil
|
257
|
+
else
|
258
|
+
if svr.respond_to?(:start_immediately)
|
259
|
+
sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
|
260
|
+
sock.sync_close = true
|
261
|
+
# we cannot do OpenSSL::SSL::SSLSocket#accept here because
|
262
|
+
# a slow client can prevent us from accepting connections
|
263
|
+
# from other clients
|
264
|
+
end
|
265
|
+
sock
|
175
266
|
end
|
176
|
-
|
267
|
+
rescue Errno::ECONNRESET, Errno::ECONNABORTED,
|
268
|
+
Errno::EPROTO, Errno::EINVAL
|
269
|
+
nil
|
270
|
+
rescue StandardError => ex
|
271
|
+
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
272
|
+
@logger.error msg
|
273
|
+
nil
|
177
274
|
end
|
178
275
|
|
276
|
+
##
|
277
|
+
# Starts a server thread for the client socket +sock+ that runs the given
|
278
|
+
# +block+.
|
279
|
+
#
|
280
|
+
# Sets the socket to the <code>:WEBrickSocket</code> thread local variable
|
281
|
+
# in the thread.
|
282
|
+
#
|
283
|
+
# If any errors occur in the block they are logged and handled.
|
284
|
+
|
179
285
|
def start_thread(sock, &block)
|
180
286
|
Thread.start{
|
181
287
|
begin
|
@@ -187,6 +293,16 @@ module WEBrick
|
|
187
293
|
@logger.debug "accept: <address unknown>"
|
188
294
|
raise
|
189
295
|
end
|
296
|
+
if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately]
|
297
|
+
WEBrick::Utils.timeout(@config[:RequestTimeout]) do
|
298
|
+
begin
|
299
|
+
sock.accept # OpenSSL::SSL::SSLSocket#accept
|
300
|
+
rescue Errno::ECONNRESET, Errno::ECONNABORTED,
|
301
|
+
Errno::EPROTO, Errno::EINVAL
|
302
|
+
Thread.exit
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
190
306
|
call_callback(:AcceptCallback, sock)
|
191
307
|
block ? block.call(sock) : run(sock)
|
192
308
|
rescue Errno::ENOTCONN
|
@@ -209,10 +325,54 @@ module WEBrick
|
|
209
325
|
}
|
210
326
|
end
|
211
327
|
|
328
|
+
##
|
329
|
+
# Calls the callback +callback_name+ from the configuration with +args+
|
330
|
+
|
212
331
|
def call_callback(callback_name, *args)
|
213
|
-
|
214
|
-
|
332
|
+
@config[callback_name]&.call(*args)
|
333
|
+
end
|
334
|
+
|
335
|
+
def setup_shutdown_pipe
|
336
|
+
return @shutdown_pipe ||= IO.pipe
|
337
|
+
end
|
338
|
+
|
339
|
+
def cleanup_shutdown_pipe(shutdown_pipe)
|
340
|
+
@shutdown_pipe = nil
|
341
|
+
shutdown_pipe&.each(&:close)
|
342
|
+
end
|
343
|
+
|
344
|
+
def alarm_shutdown_pipe
|
345
|
+
_, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe.
|
346
|
+
if pipe
|
347
|
+
if !pipe.closed?
|
348
|
+
begin
|
349
|
+
yield pipe
|
350
|
+
rescue IOError # closed by another thread.
|
351
|
+
end
|
352
|
+
end
|
215
353
|
end
|
216
354
|
end
|
355
|
+
|
356
|
+
def cleanup_listener
|
357
|
+
@listeners.each{|s|
|
358
|
+
if @logger.debug?
|
359
|
+
addr = s.addr
|
360
|
+
@logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
|
361
|
+
end
|
362
|
+
begin
|
363
|
+
s.shutdown
|
364
|
+
rescue Errno::ENOTCONN
|
365
|
+
# when `Errno::ENOTCONN: Socket is not connected' on some platforms,
|
366
|
+
# call #close instead of #shutdown.
|
367
|
+
# (ignore @config[:ShutdownSocketWithoutClose])
|
368
|
+
s.close
|
369
|
+
else
|
370
|
+
unless @config[:ShutdownSocketWithoutClose]
|
371
|
+
s.close
|
372
|
+
end
|
373
|
+
end
|
374
|
+
}
|
375
|
+
@listeners.clear
|
376
|
+
end
|
217
377
|
end # end of GenericServer
|
218
378
|
end
|