Class: ProconBypassMan::BypassCommand

Inherits:
Object
  • Object
show all
Defined in:
lib/procon_bypass_man/bypass/bypass_command.rb

Overview

子プロセスで実行する

Defined Under Namespace

Modules: WILL_TERMINATE_TOKEN

Instance Method Summary collapse

Constructor Details

#initialize(gadget:, procon:) ⇒ BypassCommand

Returns a new instance of BypassCommand.



8
9
10
11
# File 'lib/procon_bypass_man/bypass/bypass_command.rb', line 8

def initialize(gadget: , procon: )
  @gadget = gadget
  @procon = procon
end

Instance Method Details

#executeObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/procon_bypass_man/bypass/bypass_command.rb', line 13

def execute
  self_read, self_write = IO.pipe
  %w(TERM INT USR2).each do |sig|
    begin
      trap sig do
        self_write.puts(sig)
      end
    rescue ArgumentError
      puts "プロセスでSignal #{sig} not supported"
    end
  end

  # gadget => procon
  # 遅くていい
  ProconBypassMan.logger.info "[BYPASS] Thread1を起動します"

  cycle_sleep = ProconBypassMan::CycleSleep.new(cycle_interval: 1, execution_cycle: ProconBypassMan.config.bypass_mode.gadget_to_procon_interval)

  t1 = Thread.new do
    bypass = ProconBypassMan::Bypass::SwitchToProcon.new(gadget: @gadget, procon: @procon)
    loop do
      break if $will_terminate_token

      cycle_sleep.sleep_or_execute do
        bypass.run
      end
    rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
      ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
      Process.kill "TERM", Process.ppid
    rescue Errno::ETIMEDOUT => e
      # TODO まれにこれが発生する. 再接続したい
      ProconBypassMan::SendErrorCommand.execute(error: "Switchと意図せず切断されました.終了処理を開始します. #{e.full_message}")
      Process.kill "TERM", Process.ppid
    end

    ProconBypassMan.logger.info "[BYPASS] Thread1を終了します"
  end

  # procon => gadget
  # シビア
  t2 = Thread.new do
    bypass = ProconBypassMan::Bypass::ProconToSwitch.new(gadget: @gadget, procon: @procon)
    process = BlueGreenProcess.new(worker_instance: bypass, max_work: 1000)
    loop do
      if $will_terminate_token
        if $will_terminate_token == WILL_TERMINATE_TOKEN::TERMINATE
          bypass.direct_connect_switch_via_bluetooth
        end
        process.shutdown
        break
      end

      process.work

      process_switching_time_before_work = BlueGreenProcess.performance.process_switching_time_before_work
      if process_switching_time_before_work > 0.2
        ProconBypassMan::SendWarningCommand.execute(warning: "[PERFORMANCE] BlueGreenProcess.performance.process_switching_time_before_work: #{process_switching_time_before_work}", stdout: false)
      end

    rescue EOFError => e
      ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
      Process.kill "TERM", Process.ppid
      process.shutdown
      break
    rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
      ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
      Process.kill "TERM", Process.ppid
      process.shutdown
      break
    end

    ProconBypassMan.logger.info "[BYPASS] Thread2を終了します"
  end

  ProconBypassMan.logger.info "BYPASSプロセスでgraceful shutdownの準備ができました"
  begin
    # TODO: 本当はいらないんだけど、なぜか反映されないのでここでも設定する
    BlueGreenProcess.config.logger = ProconBypassMan.logger

    while(readable_io = IO.select([self_read]))
      signal = readable_io.first[0].gets.strip
      case signal
      when 'USR2'
        ProconBypassMan.logger.debug "[BYPASS] BYPASSプロセスでUSR2シグナルを受け取りました"
        raise ProconBypassMan::InterruptForRestart
      when 'TERM'
        ProconBypassMan.logger.debug "[BYPASS] BYPASSプロセスでTERMシグナルを受け取りました"
        raise Interrupt
      when 'INT'
        ProconBypassMan.logger.debug "[BYPASS] BYPASSプロセスでINTシグナルを無視します"
      end
    end
  rescue ProconBypassMan::InterruptForRestart
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセスの終了処理を開始します"
    $will_terminate_token = WILL_TERMINATE_TOKEN::RESTART
    BlueGreenProcess.terminate_workers_immediately
    [t1, t2].each(&:join)
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセス内のThreadsが停止しました"
    @gadget&.close
    @procon&.close
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセスを終了します"
    DRb.stop_service if defined?(DRb)
    exit! 1 # child processなのでexitしていい
  rescue Interrupt
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセスの終了処理を開始します"
    $will_terminate_token = WILL_TERMINATE_TOKEN::TERMINATE
    BlueGreenProcess.terminate_workers_immediately
    [t1, t2].each(&:join)
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセス内のThreadsが停止しました"
    @gadget&.close
    @procon&.close
    ProconBypassMan.logger.info "[BYPASS] BYPASSプロセスを終了します"
    DRb.stop_service if defined?(DRb)
    exit! 1 # child processなのでexitしていい
  end
end