Module: DTAS::Process

Included in:
Format, Sink, Source, Source::Command, Source::Mp3
Defined in:
lib/dtas/process.rb

Overview

:nodoc:

Constant Summary collapse

PIDS =
{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.reaperObject



9
10
11
12
13
14
15
16
17
18
# File 'lib/dtas/process.rb', line 9

def self.reaper
  begin
    pid, status = Process.waitpid2(-1, Process::WNOHANG)
    pid or return
    obj = PIDS.delete(pid)
    yield status, obj
  rescue Errno::ECHILD
    return
  end while true
end

Instance Method Details

#dtas_spawn(env, cmd, opts) ⇒ Object

for long-running processes (sox/play/ecasound filters)



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/dtas/process.rb', line 27

def dtas_spawn(env, cmd, opts)
  opts = { close_others: true, pgroup: true }.merge!(opts)

  # stringify env, integer values are easier to type unquoted as strings
  env.each { |k,v| env[k] = v.to_s }

  pid = begin
    Process.spawn(env, cmd, opts)
  rescue Errno::EINTR # Ruby bug?
    retry
  end
  warn [ :spawn, pid, cmd ].inspect if $DEBUG
  @spawn_at = Time.now.to_f
  PIDS[pid] = self
  pid
end

#qx(cmd, opts = {}) ⇒ Object

this is like backtick, but takes an array instead of a string This will also raise on errors

Raises:

  • (RuntimeError)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/dtas/process.rb', line 46

def qx(cmd, opts = {})
  r, w = IO.pipe
  opts = opts.merge(out: w)
  r.binmode
  if err = opts[:err]
    re, we = IO.pipe
    re.binmode
    opts[:err] = we
  end
  pid = begin
    Process.spawn(*cmd, opts)
  rescue Errno::EINTR # Ruby bug?
    retry
  end
  w.close
  if err
    we.close
    res = ""
    want = { r => res, re => err }
    begin
      readable = IO.select(want.keys) or next
      readable[0].each do |io|
        bytes = io.nread
        begin
          want[io] << io.read_nonblock(bytes > 0 ? bytes : 11)
        rescue Errno::EAGAIN
          # spurious wakeup, bytes may be zero
        rescue EOFError
          want.delete(io)
        end
      end
    end until want.empty?
    re.close
  else
    res = r.read
  end
  r.close
  _, status = Process.waitpid2(pid)
  return res if status.success?
  raise RuntimeError, "`#{xs(cmd)}' failed: #{status.inspect}"
end

#xs(cmd) ⇒ Object

a convienient way to display commands so it’s easy to read, copy and paste to a shell



22
23
24
# File 'lib/dtas/process.rb', line 22

def xs(cmd)
  cmd.map { |w| Shellwords.escape(w) }.join(' ')
end