class ChildProcess::Unix::PosixSpawnProcess

Private Instance Methods

fileno_for(obj) click to toggle source
# File lib/childprocess/unix/posix_spawn_process.rb, line 79
def fileno_for(obj)
  ChildProcess::JRuby.posix_fileno_for(obj)
end
launch_process() click to toggle source
# File lib/childprocess/unix/posix_spawn_process.rb, line 11
def launch_process
  pid_ptr = FFI::MemoryPointer.new(:pid_t)
  actions = Lib::FileActions.new
  attrs   = Lib::Attrs.new

  if io.stdout
    actions.add_dup fileno_for(io.stdout), fileno_for(STDOUT)
  else
    actions.add_open fileno_for(STDOUT), "/dev/null", File::WRONLY, 0644
  end

  if io.stderr
    actions.add_dup fileno_for(io.stderr), fileno_for(STDERR)
  else
    actions.add_open fileno_for(STDERR), "/dev/null", File::WRONLY, 0644
  end

  if duplex?
    reader, writer = ::IO.pipe
    actions.add_dup fileno_for(reader), fileno_for(STDIN)
    actions.add_close fileno_for(writer)
  end

  attrs.pgroup = 0 if leader?
  attrs.flags |= Platform::POSIX_SPAWN_USEVFORK if defined? Platform::POSIX_SPAWN_USEVFORK

  # wrap in helper classes in order to avoid GC'ed pointers
  argv = Argv.new(@args)
  envp = Envp.new(ENV.to_hash.merge(@environment))

  ret = 0
  @@cwd_lock.synchronize do
    Dir.chdir(@cwd || Dir.pwd) do
      if ChildProcess.jruby?
        # on JRuby, the current working directory is for some reason not inherited.
        # We'll work around it by making a chdir call through FFI.
        # TODO: report this to JRuby
        Lib.chdir Dir.pwd
      end

      ret = Lib.posix_spawnp(
        pid_ptr,
        @args.first, # TODO: not sure this matches exec() behaviour
        actions,
        attrs,
        argv,
        envp
      )
    end
  end

  if duplex?
    io._stdin = writer
    reader.close
  end

  actions.free
  attrs.free

  if ret != 0
    raise LaunchError, "#{Lib.strerror(ret)} (#{ret})"
  end

  @pid = pid_ptr.read_int
  ::Process.detach(@pid) if detach?
end