Forum: Ruby IO#popen and exit status

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Claudio J. (Guest)
on 2006-03-20 18:20
(Received via mailing list)
I'm a bit stuck with this porblem:
I need to write data to a process and then wait for the exit code of it
to
see if it was successful or not.

Now I can IO.popen the process but there is no pclose instance method to
get the exitcode back. Additionally my workaround via Process.waitpid2
does
not work either. I think io.close does already all the cleanup.

e.g.

io = IO.popen(cmd, "w")
io.write(msg)
io.close
pid, status = Process.waitpid2(0)

Raises a "Errno::ECHILD: No child processes" exception.

How do other handle this situation? Do I need to take the hard road via
pipe, fork, exec or did I miss something obvious?
Andrew J. (Guest)
on 2006-03-20 18:44
(Received via mailing list)
On Tue, 21 Mar 2006 01:20:36 +0900, Claudio J.
<removed_email_address@domain.invalid> wrote:

[snip]
> Now I can IO.popen the process but there is no pclose instance method to
> get the exitcode back. Additionally my workaround via Process.waitpid2 does
> not work either. I think io.close does already all the cleanup.

The $? variable will hold the exit status of the last child to
terminate.

andrew
unknown (Guest)
on 2006-03-20 18:59
(Received via mailing list)
On Tue, 21 Mar 2006, Claudio J. wrote:

> io = IO.popen(cmd, "w")
> io.write(msg)
> io.close
> pid, status = Process.waitpid2(0)
>
> Raises a "Errno::ECHILD: No child processes" exception.
>
> How do other handle this situation? Do I need to take the hard road via
> pipe, fork, exec or did I miss something obvious?


   gem install open4

-a
Shea M. (Guest)
on 2006-03-22 22:49
(Received via mailing list)
Andrew J. wrote:
> andrew
>
$? does not work with popen, or open3.  I am not sure why one would want
to run a  process, and monitor the output, yet not care what the exit
status is?  One would think that this oversite will be fixed in future
releases.

~S
Farrel L. (Guest)
on 2006-03-22 22:54
(Received via mailing list)
Actually I just solved this a few threads below. You can just run
Process.wait after you've done with the IO.popen and it should update
$? with the correct values.
Shea M. (Guest)
on 2006-03-22 23:04
(Received via mailing list)
Shea M. wrote:
>> The $? variable will hold the exit status of the last child to terminate.
>>
>> andrew
>>
> $? does not work with popen, or open3.  I am not sure why one would want
> to run a  process, and monitor the output, yet not care what the exit
> status is?  One would think that this oversite will be fixed in future
> releases.
>
> ~S
ps - you can call Process.wait to update $?, but it is not reliable if
your program is multi threaded.
Shea M. (Guest)
on 2006-03-22 23:14
(Received via mailing list)
> $? does not work with popen, or open3.  I am not sure why one would want
> to run a  process, and monitor the output, yet not care what the exit
> status is?  One would think that this oversite will be fixed in future
> releases.
>
> ~S

Before I get flamed, know Process.waitpid can be used...
~S
Tanaka A. (Guest)
on 2006-03-28 05:48
(Received via mailing list)
In article <removed_email_address@domain.invalid>,
  Claudio J. <removed_email_address@domain.invalid> writes:

> I'm a bit stuck with this porblem:
> I need to write data to a process and then wait for the exit code of it to
> see if it was successful or not.
>
> Now I can IO.popen the process but there is no pclose instance method to
> get the exitcode back. Additionally my workaround via Process.waitpid2 does
> not work either. I think io.close does already all the cleanup.

$? can be used after close.

I hope this documentation helps.

Index: io.c
===================================================================
RCS file: /src/ruby/io.c,v
retrieving revision 1.246.2.97
diff -u -p -r1.246.2.97 io.c
--- io.c	14 Feb 2006 02:23:33 -0000	1.246.2.97
+++ io.c	28 Mar 2006 01:47:15 -0000
@@ -2149,6 +2149,9 @@ rb_io_close(io)
  *  an <code>IOError</code> is raised if such an attempt is made. I/O
  *  streams are automatically closed when they are claimed by the
  *  garbage collector.
+ *
+ *  If <em>ios</em> is opened by <code>IO.popen</code>,
+ *  <code>close</code> sets <code>$?</code>.
  */

 static VALUE
@@ -3062,7 +3065,9 @@ retry:
  *
  *  If a block is given, Ruby will run the command as a child connected
  *  to Ruby with a pipe. Ruby's end of the pipe will be passed as a
- *  parameter to the block. In this case <code>IO::popen</code> returns
+ *  parameter to the block.
+ *  At the end of block, Ruby close the pipe and sets <code>$?</code>.
+ *  In this case <code>IO::popen</code> returns
  *  the value of the block.
  *
  *  If a block is given with a <i>cmd_string</i> of ``<code>-</code>'',
@@ -3078,6 +3083,7 @@ retry:
  *     puts "Parent is #{Process.pid}"
  *     IO.popen ("date") { |f| puts f.gets }
  *     IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is
#{f}"}
+ *     p $?
  *
  *  <em>produces:</em>
  *
@@ -3086,6 +3092,7 @@ retry:
  *     Wed Apr  9 08:53:52 CDT 2003
  *     26169 is here, f is
  *     26166 is here, f is #<IO:0x401b3d44>
+ *     #<Process::Status: pid=26166,exited(0)>
  */

 static VALUE
Roger P. (Guest)
on 2012-09-15 03:29
>> not work either. I think io.close does already all the cleanup.
>
> $? can be used after close.
>
> I hope this documentation helps.

Just so there is no confusion for others that run into this since google
brought me straight here, you can do:

a = IO.popen(process)
a.close
and $? will be set immediately after the call to close succeeds.

Process.waitpid is not necessary.
Dennis I. (Guest)
on 2015-10-28 18:13
> a = IO.popen(process)
> a.close
> and $? will be set immediately after the call to close succeeds.

Alternatively, if a block is given, at the end of block, Ruby closes the
pipe and sets `$?`.

See http://www.rubydoc.info/stdlib/core/IO.popen

"If a block is given, Ruby will run the command as a child connected to
Ruby with a pipe.
Ruby's end of the pipe will be passed as a parameter to the block.
At the end of block, Ruby closes the pipe and sets $?.
In this case IO.popen returns the value of the block."
Földes L. (Guest)
on 2015-11-03 23:08
Nice chain of topic resurrection...
This topic is locked and can not be replied to.