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