Sha256: 7ec884ab125e598bed80e4a1827fb4707d98ceb67be1623ea7981324641b7b25

Contents?: true

Size: 1.97 KB

Versions: 1

Compression:

Stored size: 1.97 KB

Contents

require 'celluloid'
require 'timeout'

module Buildbox
  class Canceler
    include Celluloid

    def initialize(build)
      @build = build
    end

    def cancel
      @build.cancel_started = true

      # Store all the child processes before we stop so we can reap them after.
      # A new process may start up between this and the process stopping,
      # but that should be OK for now.
      child_processes = process_map[@build.process.pid]

      # Stop the process
      Buildbox.logger.info "Cancelling build #{@build.namespace}/#{@build.id} with PID #{@build.process.pid}"
      @build.process.stop

      begin
        @build.process.wait
      rescue Errno::ECHILD
        # Wow! That finished quickly...
      end

      kill_processes(child_processes) if child_processes
    end

    private

    def kill_processes(processes)
      processes.each do |pid|
        Buildbox.logger.debug "Sending a TERM signal to child process with PID #{pid}"

        begin
          Process.kill("TERM", pid)

          # If the child process doesn't die within 5 seconds, try a more
          # forceful kill command
          begin
            Timeout.timeout(5) do
              Process.wait
            end
          rescue Timeout::Error
            Buildbox.logger.debug "Sending a KILL signal to child process with PID #{pid}"

            Process.kill("KILL", pid)
          rescue Errno::ECHILD
            # Killed already
          end
        rescue Errno::ESRCH
          # No such process
        end
      end
    end

    # Generates a map of parent process and child processes. This method
    # will currently only work on unix.
    def process_map
      output    = `ps -eo ppid,pid`
      processes = {}

      output.split("\n").each do |line|
        if result = line.match(/(\d+)\s(\d+)/)
          parent = result[1].to_i
          child  = result[2].to_i

          processes[parent] ||= []
          processes[parent] << child
        end
      end

      processes
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
buildbox-0.4.2 lib/buildbox/canceler.rb