Open4

Constants

VERSION

Public Class Methods

alive(pid) click to toggle source
# File lib/open4-vendor.rb, line 384
  def alive pid
#--{{{

    pid = Integer pid
    begin
      Process.kill 0, pid
      true
    rescue Errno::ESRCH
      false
    end
#--}}}

  end
Also aliased as: alive?
background(arg, *argv) click to toggle source
# File lib/open4-vendor.rb, line 336
  def background arg, *argv 
#--{{{

    require 'thread'
    q = Queue.new
    opts = { 'pid' => q, :pid => q }
    case argv.last
      when Hash
        argv.last.update opts
      else
        argv.push opts
    end
    thread = Thread.new(arg, argv){|arg, argv| spawn arg, *argv}
    sc = class << thread; self; end
    sc.module_eval {
      define_method(:pid){ @pid ||= q.pop }
      define_method(:spawn_status){ @spawn_status ||= value }
      define_method(:exitstatus){ @exitstatus ||= spawn_status.exitstatus }
    }
    thread
#--}}}

  end
Also aliased as: bg
bg(arg, *argv) click to toggle source
Alias for: background
chdir(cwd, &block) click to toggle source
# File lib/open4-vendor.rb, line 330
def chdir cwd, &block
  return(block.call Dir.pwd) unless cwd
  Dir.chdir cwd, &block
end
getopts(opts = {}) click to toggle source
# File lib/open4-vendor.rb, line 181
  def getopts opts = {}
#--{{{

    lambda do |*args|
      keys, default, ignored = args
      catch('opt') do
        [keys].flatten.each do |key|
          [key, key.to_s, key.to_s.intern].each do |key|
            throw 'opt', opts[key] if opts.has_key?(key)
          end
        end
        default
      end
    end
#--}}}

  end
maim(pid, opts = {}) click to toggle source
# File lib/open4-vendor.rb, line 361
  def maim pid, opts = {}
#--{{{

    getopt = getopts opts
    sigs = getopt[ 'signals', %(SIGTERM SIGQUIT SIGKILL) ]
    suspend = getopt[ 'suspend', 4 ]
    pid = Integer pid
    existed = false
    sigs.each do |sig|
      begin
        Process.kill sig, pid
        existed = true 
      rescue Errno::ESRCH
        return(existed ? nil : true)
      end
      return true unless alive? pid
      sleep suspend
      return true unless alive? pid
    end
    return(not alive?(pid)) 
#--}}}

  end
new_thread(*a, &b) click to toggle source
# File lib/open4-vendor.rb, line 167
  def new_thread *a, &b
#--{{{

    cur = Thread.current
    Thread.new(*a) do |*a|
      begin
        b[*a]
      rescue Exception => e
        cur.raise e
      end
    end
#--}}}

  end
open4(*cmd, &b) click to toggle source
Alias for: popen4
popen4(*cmd, &b) click to toggle source
# File lib/open4-vendor.rb, line 13
  def popen4(*cmd, &b)
#--{{{

    pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe

    verbose = $VERBOSE
    begin
      $VERBOSE = nil
      ps.first.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
      ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)

      cid = fork {
        pw.last.close
        STDIN.reopen pw.first
        pw.first.close

        pr.first.close
        STDOUT.reopen pr.last
        pr.last.close

        pe.first.close
        STDERR.reopen pe.last
        pe.last.close

        STDOUT.sync = STDERR.sync = true

        begin
          exec(*cmd)
          raise 'forty-two' 
        rescue Exception => e
          Marshal.dump(e, ps.last)
          ps.last.flush
        end
        ps.last.close unless (ps.last.closed?)
        exit!
      }
    ensure
      $VERBOSE = verbose
    end

    [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}

    begin
      e = Marshal.load ps.first
      raise(Exception === e ? e : "unknown failure!")
    rescue EOFError # If we get an EOF error, then the exec was successful

      42
    ensure
      ps.first.close
    end

    pw.last.sync = true

    pi = [pw.last, pr.first, pe.first]

    if b 
      begin
        b[cid, *pi]
        Process.waitpid2(cid).last
      ensure
        pi.each{|fd| fd.close unless fd.closed?}
      end
    else
      [cid, pw.last, pr.first, pe.first]
    end
#--}}}

  end
Also aliased as: open4
relay(src, dst = nil, t = nil) click to toggle source
# File lib/open4-vendor.rb, line 198
  def relay src, dst = nil, t = nil
#--{{{

    send_dst =
      if dst.respond_to?(:call)
        lambda{|buf| dst.call(buf)}
      else
        lambda{|buf| dst << buf}
      end

    unless src.nil?
      if src.respond_to? :gets
        while buf = to(t){ src.gets }
          send_dst[buf]
        end

      elsif src.respond_to? :each
        q = Queue.new
        th = nil

        timer_set = lambda do |t|
          th = new_thread{ to(t){ q.pop } }
        end

        timer_cancel = lambda do |t|
          th.kill if th rescue nil
        end

        timer_set[t]
        begin
          src.each do |buf|
            timer_cancel[t]
            send_dst[buf]
            timer_set[t]
          end
        ensure
          timer_cancel[t]
        end

      elsif src.respond_to? :read
        buf = to(t){ src.read }
        send_dst[buf]

      else
        buf = to(t){ src.to_s }
        send_dst[buf]
      end
    end
#--}}}

  end
spawn(arg, *argv) click to toggle source
# File lib/open4-vendor.rb, line 249
  def spawn arg, *argv 
#--{{{

    argv.unshift(arg)
    opts = ((argv.size > 1 and Hash === argv.last) ? argv.pop : {})
    argv.flatten!
    cmd = argv.join(' ')


    getopt = getopts opts

    ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
    ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
    exitstatus = getopt[ %( exitstatus exit_status status ) ]
    stdin = getopt[ %( stdin in i 0 ) << 0 ]
    stdout = getopt[ %( stdout out o 1 ) << 1 ]
    stderr = getopt[ %( stderr err e 2 ) << 2 ]
    pid = getopt[ 'pid' ]
    timeout = getopt[ %( timeout spawn_timeout ) ]
    stdin_timeout = getopt[ %( stdin_timeout ) ]
    stdout_timeout = getopt[ %( stdout_timeout io_timeout ) ]
    stderr_timeout = getopt[ %( stderr_timeout ) ]
    status = getopt[ %( status ) ]
    cwd = getopt[ %( cwd dir ) ]

    exitstatus =
      case exitstatus
        when TrueClass, FalseClass
          ignore_exit_failure = true if exitstatus
          [0]
        else
          [*(exitstatus || 0)].map{|i| Integer i}
      end

    stdin ||= '' if stdin_timeout
    stdout ||= '' if stdout_timeout
    stderr ||= '' if stderr_timeout

    started = false

    status =
      begin
        chdir(cwd) do
          Timeout::timeout(timeout) do
            popen4(*argv) do |c, i, o, e|
              started = true

              %( replace pid= << push update ).each do |msg|
                break(pid.send(msg, c)) if pid.respond_to? msg 
              end

              te = ThreadEnsemble.new c

              te.add_thread(i, stdin) do |i, stdin|
                relay stdin, i, stdin_timeout
                i.close rescue nil
              end

              te.add_thread(o, stdout) do |o, stdout|
                relay o, stdout, stdout_timeout
              end

              te.add_thread(e, stderr) do |o, stderr|
                relay e, stderr, stderr_timeout
              end

              te.run
            end
          end
        end
      rescue
        raise unless(not started and ignore_exec_failure)
      end

    raise SpawnError.new(cmd, status) unless
      (ignore_exit_failure or (status.nil? and ignore_exec_failure) or exitstatus.include?(status.exitstatus))

    status
#--}}}

  end
to(timeout = nil) click to toggle source
# File lib/open4-vendor.rb, line 160
  def to timeout = nil
#--{{{

    Timeout.timeout(timeout){ yield }
#--}}}

  end
version() click to toggle source
# File lib/open4-vendor.rb, line 9
def self.version() VERSION end

Public Instance Methods

alive?(pid) click to toggle source
Alias for: alive

[Validate]

Generated with the Darkfish Rdoc Generator 2.