Class: Shrimple::Process

Inherits:
Object
  • Object
show all
Defined in:
lib/shrimple/process.rb

Direct Known Subclasses

Phantom

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cmd, inio, outio, errio, timeout = nil) ⇒ Process

runs cmd, passes instr on its stdin, and fills outio and errio with the command’s output.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/shrimple/process.rb', line 15

def initialize cmd, inio, outio, errio, timeout=nil
  @start_time = Time.now
  @chin, @chout, @cherr, @child = Open3.popen3(*cmd)

  Shrimple.processes._add(self)
  @chout.binmode

  @killed = false
  @timed_out = false

  @thrin  = Thread.new { drain(inio, @chin) }
  @throut = Thread.new { drain(@chout, outio) }
  @threrr = Thread.new { drain(@cherr, errio) }

  # ensure cleanup is called when the child exits. (strange it requires a whole new thread...?)
  @thrchild = Thread.new {
    if timeout
      outatime unless @child.join(timeout)
    else
      @child.join
    end
    stop
  }
end

Instance Attribute Details

#start_timeObject (readonly)

start and finish times of Phantom process



11
12
13
# File 'lib/shrimple/process.rb', line 11

def start_time
  @start_time
end

#stop_timeObject (readonly)

start and finish times of Phantom process



11
12
13
# File 'lib/shrimple/process.rb', line 11

def stop_time
  @stop_time
end

Instance Method Details

#_child_threadObject

only meant to be used by the ProcessMonitor



83
84
85
# File 'lib/shrimple/process.rb', line 83

def _child_thread
  @child
end

#_cleanupObject

may only be called once, synchronized by stop()



88
89
90
91
# File 'lib/shrimple/process.rb', line 88

def _cleanup
  raise "Someone else already stopped this process??!!" if @stop_time
  @stop_time = Time.now
end

#_deactivateObject

returns true if process was previously active. must be externally synchronized.



94
95
96
97
98
# File 'lib/shrimple/process.rb', line 94

def _deactivate
  retval = @inactive
  @inactive = true
  return !retval
end

#finished?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/shrimple/process.rb', line 41

def finished?
  @stop_time != nil
end

#kill(seconds_until_panic = 2) ⇒ Object

kill-o-zaps the phantom process now (using -9 if needed), then waits until it’s truly gone



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/shrimple/process.rb', line 59

def kill seconds_until_panic=2
  @killed = true
  if @child.alive?
    # rescue because process might have died between previous line and this one
    ::Process.kill("TERM", @child.pid) rescue Errno::ESRCH
  end
  if !@child.join(seconds_until_panic)
    ::Process.kill("KILL", @child.pid) if @child.alive?
  end
  # ensure kill doesn't return until process is truly gone
  # (there may be a chance of this deadlocking with a blocking callback... not sure)
  @thrchild.join unless Thread.current == @thrchild
end

#killed?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/shrimple/process.rb', line 50

def killed?
  @killed
end

#stopObject

waits patiently until phantom process terminates, then cleans up



74
75
76
77
78
79
# File 'lib/shrimple/process.rb', line 74

def stop
  wait_for_the_end   # do all our waiting outside the sync loop
  Shrimple.processes._remove(self) do
    _cleanup
  end
end

#success?Boolean

returns false if the process hasn’t finished yet

Returns:

  • (Boolean)


46
47
48
# File 'lib/shrimple/process.rb', line 46

def success?
  finished? && @child.value.success? ? true : false
end

#timed_out?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/shrimple/process.rb', line 54

def timed_out?
  @timed_out
end