lib/tork/server.rb in tork-19.0.0 vs lib/tork/server.rb in tork-19.0.1
- old
+ new
@@ -1,9 +1,9 @@
require 'socket'
-require 'thread'
require 'json'
require 'shellwords'
+require 'set'
module Tork
class Server
def self.address program=$0
@@ -14,24 +14,24 @@
# only JSON messages are supposed to be emitted on STDOUT
# so make puts() in the user code write to STDERR instead
@stdout = STDOUT.dup
STDOUT.reopen STDERR
- @clients = [STDIN]
- @servers = []
+ @clients = Set.new.add(STDIN)
+ @servers = Set.new
end
def loop
server = UNIXServer.open(Server.address)
- @servers << server
+ @servers.add server
catch :quit do
while @clients.include? STDIN
- IO.select(@servers + @clients).first.each do |stream|
+ IO.select((@servers + @clients).to_a).first.each do |stream|
@client = stream
if stream == server
- @clients << stream.accept
+ @clients.add stream.accept
elsif (stream.eof? rescue true)
@clients.delete stream
elsif @command = hear(stream, stream.gets)
@@ -49,36 +49,28 @@
throw :quit
end
protected
- JSON_REGEXP = /\A\s*[\[\{]/.freeze
-
- # On failure to decode the message, warns the sender and returns nil.
+ # Returns nil if the message received was not meant for processing.
def hear sender, message
- if message =~ JSON_REGEXP
- JSON.load message
-
- # accept non-JSON "command lines" from clients
- elsif @clients.include? sender
+ JSON.load message
+ rescue JSON::ParserError => error
+ if @clients.include? sender
+ # accept non-JSON "command lines" from clients
Shellwords.split message
-
- # forward tell() output from children to clients
- elsif @servers.include? sender
+ else
+ # forward tell() output from servers to clients
tell @clients, message, false
nil
end
- rescue JSON::ParserError => error
- tell sender, error
- nil
end
def recv client, command
__send__(*command)
rescue => error
tell client, error
- nil
end
def send one_or_more_clients, message
tell one_or_more_clients, JSON.dump(message), false
end
@@ -106,22 +98,22 @@
end
end
def popen command
child = IO.popen(command, 'r+')
- @servers << child
+ @servers.add child
child
end
def pclose child
- return unless @servers.delete child
+ return unless @servers.delete? child
# this should be enough to stop programs that use Tork::Server#loop
# because their IO.select() loop terminates on the closing of STDIN
child.close_write
# but some programs like tork-herald(1) need to be killed explicitly
- # because they do not follow this convention of exiting on STDIN close
+ # because they do not follow our convention of exiting on STDIN close
Process.kill :SIGTERM, child.pid
Process.waitpid child.pid
# this will block until the child process has exited so we must kill it
# explicitly (as above) to ensure that this program does not hang here