System calls

Don’t know if this helps but I recall that in perl you have to divide by
256 to get the real return value. (Tried to test here but running under
Windows and therefore have no ‘fork’ to eat really_cool_system with).

All the best,

Jon

···

-----Original Message-----
From: Brian Candler [mailto:B.Candler@pobox.com]
Sent: 27 May 2003 17:48
To: ruby-talk ML
Subject: Re: system calls

On Tue, May 27, 2003 at 10:24:50PM +0900, mgarriss wrote:

so I can get the standard output from a system call:

s = date

and I can get the return value:

system( “date” )

and I have no idea how to get the standard error:

???

but what I really want is all three, like:

out, err, ret = really_cool_system( “date” )

This is almost what you want, except that the exit code is wrong and I
don’t
know how to fix it:

require ‘open3’
module Kernel
private
def really_cool_system(*args)
inp, out, err = Open3.popen3(*args)
ret1 = ret2 = nil
t1 = Thread.new do
inp.close
end
t2 = Thread.new do
ret1 = out.read
out.close
end
t3 = Thread.new do
ret2 = err.read
err.close
end
t1.join
t2.join
t3.join
return ret1, ret2, $?
end
end

irb(main):024:0> really_cool_system(“ls”,“/dev/null”,“/dev/foo”)
=> [“/dev/null\n”, “ls: /dev/foo: No such file or directory\n”, 65280]

Regards,

Brian.


This e-mail has been scanned for all viruses by Star Internet. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk



This message has been checked for all known viruses by Star Internet delivered
through the MessageLabs Virus Control Centre. For further information visit
http://www.star.net.uk/stats.asp


Any views or personal opinions expressed within this email may not be those of Talis Information Ltd.
The content of this email message and any files that may be attached are confidential, and for the usage of the intended recipient only. If you are not the intended recipient, then please return this message to the sender and delete it. Any use of this e-mail by an unauthorised recipient is prohibited.

Hmm, I thought that Windows (32 bit) did have those things. Oh well.

The problem is not that the exit code needs to be divided by 256 (which
indeed it does), but that it’s wrong: 65280 gives an exit code of 255, even
though the process terminated correctly with an exit code of 0.

Regards,

Brian.

···

On Wed, May 28, 2003 at 01:56:41AM +0900, J.Hawkesworth wrote:

Don’t know if this helps but I recall that in perl you have to divide by
256 to get the real return value. (Tried to test here but running under
Windows and therefore have no ‘fork’ to eat really_cool_system with).

This is because the reason for the program termination (e.g. caught a
signal, called exit,…) is encoded in the least significant 8 bits.

Maybe, a absolutly_gorgous_system() should report this too… :wink:

greetings, Florian Pflug

···

On Wed, May 28, 2003 at 01:56:41AM +0900, J.Hawkesworth wrote:

Don’t know if this helps but I recall that in perl you have to divide by
256 to get the real return value. (Tried to test here but running under
Windows and therefore have no ‘fork’ to eat really_cool_system with).

Yes, it’s broken: true and false (which return 0 and 1 respectively)
give the same value.

The problem is in Open3.popen3. It forks twice, so the command it runs
isn’t Ruby’s child. (I don’t know why you’d want this.) That means $?
is the return from the first fork, or something like that. There could
be races also.

To be used in a program with it’s own children, you’d want to waitpid on
the system call you spawned to get it’s return value. I think
Open3.popen3 should return [in, out, err, pid] so you could do this, but
it doesn’t, so you can’t. Without waiting on the pid of your child, you
can’t reliably get the return value.

···

On Tue, 2003-05-27 at 11:56, J.Hawkesworth wrote:

This is almost what you want, except that the exit code is wrong and I
don’t
know how to fix it:

require ‘open3’
module Kernel
private
def really_cool_system(*args)
inp, out, err = Open3.popen3(*args)
ret1 = ret2 = nil
t1 = Thread.new do
inp.close
end
t2 = Thread.new do
ret1 = out.read
out.close
end
t3 = Thread.new do
ret2 = err.read
err.close
end
t1.join
t2.join
t3.join
return ret1, ret2, $?
end
end

irb(main):024:0> really_cool_system(“ls”,“/dev/null”,“/dev/foo”)
=> [“/dev/null\n”, “ls: /dev/foo: No such file or directory\n”, 65280]

Regards,

Brian.


Tom Felker

They made a crude but listenable crystal radio out of a light bulb, a
crayon, a square of toilet paper, and a rock. They say they’ll have
Linux running on it by next week.

Florian G. Pflug wrote:

···

On Wed, May 28, 2003 at 01:56:41AM +0900, J.Hawkesworth wrote:

Don’t know if this helps but I recall that in perl you have to divide by
256 to get the real return value. (Tried to test here but running under
Windows and therefore have no ‘fork’ to eat really_cool_system with).

This is because the reason for the program termination (e.g. caught a
signal, called exit,…) is encoded in the least significant 8 bits.

Ruby 1.8 encapsulates this in a Process::Status object:

dave[ruby/rdoc 17:07:36] ri Process::Status
This is a test ‘ri’. Please report errors and omissions
on http://www.rubygarden.org/ruby?RIOnePointEight


  class: Process::Status

  Process::Status encapsulates the information on the status of a
  running or terminated system process. The built-in variable $? is
  either nil or a Process::Status object.
     fork { exit 99 }   #=> 26557
     Process.wait       #=> 26557
     $?.class           #=> Process::Status
     $?.to_i            #=> 25344
     $? >> 8            #=> 99
     $?.stopped?        #=> false
     $?.exited?         #=> true
     $?.exitstatus      #=> 99
  Posix system record information on processes using a 16-bit
  integer. The lower bits recorded the process status (stopped,
  exited, signaled) and the upper bits possibly contain additional
  information (for example the program's return code in the case of
  exited processes). Pre Ruby 1.8, these bits were exposed directly
  to the Ruby program. Ruby now encapsulates these in a
  Process::Status object. To maximize compatibility, however, these
  objects retain a bit-oriented interface. In the descriptions that
  follow, when we talk about the integer value of stat, we're
  referring to this 16 bit value.

  &, ==, >>, coredump?, exited?, exitstatus, inspect, pid, signaled?,
  stopped?, stopsig, termsig, to_i, to_int, to_s