I searched around but I cannot get to understand why I am getting the error:
"in `spawn': no implicit conversion of IO into String"
for the following simple method
def execute_with_timeout(cmd)
pipe_cmd_out = IO.pipe
pid = Process.spawn(cmd, :out => pipe_cmd_out, :pgroup => true)
Process.waitpid(pid, 0)
pipe_cmd_out.close
$?.exitstatus == 0
end
where am I making the error here?
The redirection maps a file descriptor in the child process, e.g. :out
(or STDOUT
or 1
) to one of:
From the pipe() docs:
pipe() -> [read_io, write_o]:
Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element array of IO objects: [ read_io, write_io ].
http://ruby-doc.org/core-2.2.0/IO.html#method-c-pipe
So, you can do this:
def execute_with_timeout(cmd)
reader, writer = IO.pipe
puts reader, writer
pid = Process.spawn(
cmd,
:pgroup => true,
:out => writer.fileno, #Redirect child STDOUT into one end of the pipe.
)
Process.waitpid(pid, 0)
puts reader.gets #Read from the other end of the pipe in the parent.
writer.close
reader.close
$?.exitstatus == 0
end
result = execute_with_timeout('ls')
puts result
--output:--
#<IO:0x000001009a0140>
#<IO:0x000001009a0118>
1.rb
true
where am I making the error here?
The spawn() docs say:
For redirecting to a file, an array is used instead:
id = spawn(command, :out=>["log", "w"])
The array specifies a filename, flags and permission.
http://ruby-doc.org/core-2.1.3/Process.html#method-c-spawn
Your pipe() call returns an array of IO objects, which you used for the value of the :out key. But because spawn() is expecting an array of Strings as a value, ruby tries to convert the IO objects to Strings, which produces the error:
"in `spawn': no implicit conversion of IO into String"
The spawn() docs do show an example where the value corresponding to one of the redirect keys is not an array of strings:
:err=>[:child, :out]
(which means redirect :err
(in the child) to child :out
). But your pipe() array is not an array of Symbols either.