def launch_process
if @io
stdout = @io.stdout
stderr = @io.stderr
end
exec_r, exec_w = ::IO.pipe
ChildProcess.close_on_exec exec_w
if duplex?
reader, writer = ::IO.pipe
end
@pid = fork {
if @cwd
Dir.chdir(@cwd)
end
exec_r.close
set_env
STDOUT.reopen(stdout || "/dev/null")
STDERR.reopen(stderr || "/dev/null")
if duplex?
STDIN.reopen(reader)
writer.close
end
begin
exec(*@args)
rescue SystemCallError => ex
exec_w << ex.message
end
}
exec_w.close
if duplex?
io._stdin = writer
reader.close
end
unless exec_r.eof?
raise LaunchError, exec_r.read || "executing command with #{@args.inspect} failed"
end
::Process.detach(@pid) if detach?
end