Class: Chocomint::Console::WorkerProcess
- Inherits:
-
Object
- Object
- Chocomint::Console::WorkerProcess
show all
- Defined in:
- lib/chocomint/console/worker_process.rb
Overview
コンソールワーカーを「新規コンソール付き」で spawn し、名前付きパイプで
双方向にやり取りするための橋渡し。
なぜ名前付きパイプか (重要): ConPTY はコンソール付きプロセスからしか
正しく動かない (chocomint-conpty メモの制約)。CREATE_NEW_CONSOLE で新規
コンソールを与える必要があるが、STARTF_USESTDHANDLES で stdout をパイプへ
リダイレクトすると新規コンソールとの関連付けが壊れ、ConPTY 出力が 16 バイトの
初期シーケンスで止まる (実測で確認)。そこで stdio は触らず、制御通信は
独立した名前付きパイプで行う。ワーカーはコンソールを完全に保持できる。
Defined Under Namespace
Modules: Native
Classes: Error
Instance Method Summary
collapse
Constructor Details
#initialize(command:, cols:, rows:, cwd:, ruby_exe: nil, worker_script: nil) ⇒ WorkerProcess
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/chocomint/console/worker_process.rb', line 69
def initialize(command:, cols:, rows:, cwd:, ruby_exe: nil, worker_script: nil)
@command = command
@cols = cols
@rows = rows
@cwd = cwd
@ruby_exe = ruby_exe || default_ruby_exe
@worker_script = worker_script || default_worker_script
base = "\\\\.\\pipe\\chocomint-console-#{SecureRandom.hex(8)}"
@c2w_name = "#{base}-c2w"
@w2c_name = "#{base}-w2c"
@open = false
end
|
Instance Method Details
#alive? ⇒ Boolean
124
125
126
127
128
129
130
131
|
# File 'lib/chocomint/console/worker_process.rb', line 124
def alive?
return false unless @proc_handle
code = FFI::MemoryPointer.new(:uint32)
return false if Native.GetExitCodeProcess(@proc_handle, code).zero?
code.read(:uint32) == Native::STILL_ACTIVE
end
|
#close ⇒ Object
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/chocomint/console/worker_process.rb', line 133
def close
return unless @open
Native.TerminateProcess(@proc_handle, 0) if alive?
[@c2w, @w2c].each do |h|
next unless h
Native.DisconnectNamedPipe(h)
Native.CloseHandle(h)
end
Native.CloseHandle(@proc_handle) if @proc_handle
@open = false
nil
end
|
#open? ⇒ Boolean
84
85
86
|
# File 'lib/chocomint/console/worker_process.rb', line 84
def open?
@open
end
|
#read_message ⇒ Object
ワーカーからの JSON 行を 1 つ読む。無ければ nil (ノンブロッキング)。
115
116
117
118
119
120
121
122
|
# File 'lib/chocomint/console/worker_process.rb', line 115
def read_message
line = read_line
return nil if line.nil? || line.empty?
JSON.parse(line)
rescue JSON::ParserError
nil
end
|
106
107
108
|
# File 'lib/chocomint/console/worker_process.rb', line 106
def send_input(bytes)
send_message("type" => "input", "data" => Base64.strict_encode64(bytes.b))
end
|
#send_message(hash) ⇒ Object
102
103
104
|
# File 'lib/chocomint/console/worker_process.rb', line 102
def send_message(hash)
write_bytes("#{JSON.generate(hash)}\n".b)
end
|
#send_resize(cols, rows) ⇒ Object
110
111
112
|
# File 'lib/chocomint/console/worker_process.rb', line 110
def send_resize(cols, rows)
send_message("type" => "resize", "cols" => cols, "rows" => rows)
end
|
#start ⇒ Object
名前付きパイプを 2 本作り、ワーカーを新規コンソール付きで spawn して接続を待つ。
89
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/chocomint/console/worker_process.rb', line 89
def start
raise Error, "already started" if @open
@c2w = create_named_pipe(@c2w_name)
@w2c = create_named_pipe(@w2c_name)
spawn_worker
Native.ConnectNamedPipe(@c2w, nil)
Native.ConnectNamedPipe(@w2c, nil)
@open = true
self
end
|