Class: Async::Container::Process

Inherits:
Channel
  • Object
show all
Defined in:
lib/async/container/process.rb

Overview

Represents a running child process from the point of view of the parent container.

Defined Under Namespace

Classes: Instance

Instance Attribute Summary collapse

Attributes inherited from Channel

#in, #out

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Channel

#close_read, #close_write, #receive

Constructor Details

#initialize(name: nil) ⇒ Process

Initialize the process.



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/async/container/process.rb', line 114

def initialize(name: nil)
	super()
	
	@name = name
	@status = nil
	@pid = nil
	
	@pid = yield(self)
	
	# The parent process won't be writing to the channel:
	self.close_write
end

Instance Attribute Details

#nameObject

The name of the process.



138
139
140
# File 'lib/async/container/process.rb', line 138

def name
  @name
end

Class Method Details

.fork(**options) ⇒ Object

Fork a child process appropriate for a container.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/async/container/process.rb', line 83

def self.fork(**options)
	self.new(**options) do |process|
		::Process.fork do
			Signal.trap(:INT) {raise Interrupt}
			Signal.trap(:TERM) {raise Terminate}
			
			begin
				yield Instance.for(process)
			rescue Interrupt
				# Graceful exit.
			rescue Exception => error
				Console.logger.error(self) {error}
				
				exit!(1)
			end
		end
	end
end

Instance Method Details

#closeObject

Invoke #terminate! and then #wait for the child process to exit.



147
148
149
150
151
152
# File 'lib/async/container/process.rb', line 147

def close
	self.terminate!
	self.wait
ensure
	super
end

#interrupt!Object

Send ‘SIGINT` to the child process.



155
156
157
158
159
# File 'lib/async/container/process.rb', line 155

def interrupt!
	unless @status
		::Process.kill(:INT, @pid)
	end
end

#terminate!Object

Send ‘SIGTERM` to the child process.



162
163
164
165
166
# File 'lib/async/container/process.rb', line 162

def terminate!
	unless @status
		::Process.kill(:TERM, @pid)
	end
end

#to_sObject

A human readable representation of the process.



142
143
144
# File 'lib/async/container/process.rb', line 142

def to_s
	"\#<#{self.class} #{@name}>"
end

#waitObject

Wait for the child process to exit.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/async/container/process.rb', line 170

def wait
	if @pid && @status.nil?
		_, @status = ::Process.wait2(@pid, ::Process::WNOHANG)
		
		if @status.nil?
			sleep(0.01)
			_, @status = ::Process.wait2(@pid, ::Process::WNOHANG)
		end
		
		if @status.nil?
			Console.logger.warn(self) {"Process #{@pid} is blocking, has it exited?"}
			_, @status = ::Process.wait2(@pid)
		end
	end
	
	return @status
end