lib/ftw/server.rb in ftw-0.0.41 vs lib/ftw/server.rb in ftw-0.0.42

- old
+ new

@@ -24,10 +24,11 @@ # is missing, it is assumed to be 0.0.0.0 def initialize(addresses) addresses = [addresses] if !addresses.is_a?(Array) dns = FTW::DNS.singleton + @control_lock = Mutex.new @sockets = {} failures = [] # address format is assumed to be 'host:port' # TODO(sissel): The split on ":" breaks ipv6 addresses, yo. @@ -76,32 +77,44 @@ break end failures += local_failures end + # This allows us to interrupt the #each_connection's select() later + # when anyone calls stop() + @stopper = IO.pipe + # Abort if there were failures raise ServerSetupFailure.new(failures) if failures.any? end # def initialize # Stop serving. def stop - @sockets.each do |name, socket| - socket.close + @stopper[1].syswrite(".") + @stopper[1].close() + @control_lock.synchronize do + @sockets.each do |name, socket| + socket.close + end + @sockets.clear end end # def stop # Yield FTW::Connection instances to the block as clients connect. def each_connection(&block) # TODO(sissel): Select on all sockets # TODO(sissel): Accept and yield to the block + stopper = @stopper[0] while true - sockets = @sockets.values - read, write, error = IO.select(sockets, nil, nil, nil) - read.each do |serversocket| - #p serversocket.methods.sort - socket, addrinfo = serversocket.accept - connection = FTW::Connection.from_io(socket) - yield connection + @control_lock.synchronize do + sockets = @sockets.values + [stopper] + read, write, error = IO.select(sockets, nil, nil, nil) + break if read.include?(stopper) + read.each do |serversocket| + socket, addrinfo = serversocket.accept + connection = FTW::Connection.from_io(socket) + yield connection + end end end end # def each_connection public(:initialize, :stop, :each_connection)