Class: Async::Container::Process

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

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

def self.spawn(*arguments, name: nil, **options) self.new(name: name) do |process| unless options.key?(:out) options[:out] = process.out end

    ::Process.spawn(*arguments, **options)
end

end



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/async/container/process.rb', line 99

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

Returns the value of attribute name.



119
120
121
# File 'lib/async/container/process.rb', line 119

def name
  @name
end

Class Method Details

.fork(**options) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/async/container/process.rb', line 70

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
        Async.logger.error(self) {error}
        
        exit!(1)
      end
    end
  end
end

Instance Method Details

#closeObject



125
126
127
128
129
130
# File 'lib/async/container/process.rb', line 125

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

#interrupt!Object



132
133
134
135
136
# File 'lib/async/container/process.rb', line 132

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

#terminate!Object



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

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

#to_sObject



121
122
123
# File 'lib/async/container/process.rb', line 121

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

#waitObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/async/container/process.rb', line 144

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?
      Async.logger.warn(self) {"Process #{@pid} is blocking, has it exited?"}
      _, @status = ::Process.wait2(@pid)
    end
  end
  
  return @status
end