# MAIN
#
+ShogiServer.reload
+
def gets_safe(socket, timeout=nil)
if r = select([socket], nil, nil, timeout)
return r[0].first.gets
return :timeout
end
rescue Exception => ex
- log_error("#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
+ log_error("gets_safe: #{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
return :exception
end
specify filename for logging process ID
--daemon dir
run as a daemon. Log files will be put in dir.
+ --player-log-dir dir
+ log network messages for each player. Log files
+ will be put in the dir.
LICENSE
GPL versoin 2 or later
options = Hash::new
parser = GetoptLong.new(
["--daemon", GetoptLong::REQUIRED_ARGUMENT],
- ["--pid-file", GetoptLong::REQUIRED_ARGUMENT])
+ ["--pid-file", GetoptLong::REQUIRED_ARGUMENT],
+ ["--player-log-dir", GetoptLong::REQUIRED_ARGUMENT])
parser.quiet = true
begin
parser.each_option do |name, arg|
end
def mutex_watchdog(mutex, sec)
+ sec = 1 if sec < 1
+ queue = []
while true
- begin
- timeout(sec) do
- begin
- mutex.lock
- ensure
- mutex.unlock
- end
+ if mutex.try_lock
+ queue.clear
+ mutex.unlock
+ else
+ queue.push(Object.new)
+ if queue.size > sec
+ # timeout
+ log_error("mutex watchdog timeout: %d sec" % [sec])
+ queue.clear
end
- sleep(sec)
- rescue TimeoutError
- log_error("mutex watchdog timeout")
- exit(1)
end
+ sleep(1)
end
end
def setup_logger(log_file)
logger = Logger.new(log_file, 'daily')
logger.formatter = ShogiServer::Formatter.new
- logger.level = Logger::INFO
+ logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO
logger.datetime_format = "%Y-%m-%d %H:%M:%S"
return logger
end
end
end
-def main
+def setup_floodgate
+ return Thread.start do
+ Thread.pass
+ floodgate = ShogiServer::League::Floodgate.new(LEAGUE)
+ log_message("Flooddgate reloaded. The next match will start at %s." %
+ [floodgate.next_time])
+
+ while (true)
+ begin
+ diff = floodgate.next_time - Time.now
+ if diff > 0
+ sleep(diff/2)
+ next
+ end
+ LEAGUE.reload
+ floodgate.match_game
+ floodgate.charge
+ next_time = floodgate.next_time
+ $mutex.synchronize do
+ log_message("Reloading source...")
+ ShogiServer.reload
+ end
+ floodgate = ShogiServer::League::Floodgate.new(LEAGUE, next_time)
+ log_message("Floodgate will start the next match at %s." %
+ [floodgate.next_time])
+ rescue Exception => ex
+ # ignore errors
+ log_error("[in Floodgate's thread] #{ex} #{ex.backtrace}")
+ end
+ end
+ end
+end
- setup_watchdog_for_giant_lock
+def main
+
+ setup_watchdog_for_giant_lock
$options = parse_command_line
if (ARGV.length != 2)
usage
exit 2
end
+ if $options["player-log-dir"]
+ $options["player-log-dir"] = File.expand_path($options["player-log-dir"])
+ end
+ if $options["player-log-dir"] &&
+ !File.directory?($options["player-log-dir"])
+ usage
+ exit 3
+ end
LEAGUE.event = ARGV.shift
port = ARGV.shift
config[:Port] = port
config[:ServerType] = WEBrick::Daemon if $options["daemon"]
config[:Logger] = $logger
- if $options["pid-file"]
- pid_file = File.expand_path($options["pid-file"])
- config[:StartCallback] = Proc.new do
- write_pid_file(pid_file)
+
+ fg_thread = nil
+ config[:StartCallback] = Proc.new do
+ if $options["pid-file"]
+ write_pid_file($options["pid-file"])
end
- config[:StopCallback] = Proc.new do
+ fg_thread = setup_floodgate
+ end
+
+ config[:StopCallback] = Proc.new do
+ if $options["pid-file"]
FileUtils.rm(pid_file, :force => true)
end
end
server = WEBrick::GenericServer.new(config)
["INT", "TERM"].each do |signal|
trap(signal) do
- LEAGUE.shutdown
server.shutdown
+ fg_thread.kill if fg_thread
end
end
trap("HUP") do
- LEAGUE.shutdown
Dependencies.clear
- LEAGUE.restart
end
$stderr.puts("server started as a deamon [Revision: #{ShogiServer::Revision}]") if $options["daemon"]
log_message("server started [Revision: #{ShogiServer::Revision}]")
log_message(sprintf("user %s login", player.name))
login.process
+ player.setup_logger($options["player-log-dir"]) if $options["player-log-dir"]
player.run(login.csa_1st_str) # loop
$mutex.lock
begin
TCPSocket.do_not_reverse_lookup = true
Thread.abort_on_exception = $DEBUG ? true : false
+ begin
LEAGUE = ShogiServer::League::new
- main
+ main
+ rescue Exception => ex
+ log_error("main: #{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
+ end
end