Project

General

Profile

Actions

Feature #16791

open

Shortcut for Process::Status.exitstatus

Added by 0x81000000 (/ /) about 4 years ago. Updated almost 4 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:97905]

Description

[Updated]

s = `csc x.cs`.sub(/.*?\n\n/m, '')
puts s if s != '';   exit $?.exitstatus if $?.exitstatus > 0
system 'mono x.exe'; exit $?.exitstatus
class Process::Status
    alias :es :exitstatus
end
s = `csc x.cs`.sub(/.*?\n\n/m, '')
puts s if s != '';   exit $?.es if $?.es > 0
system 'mono x.exe'; exit $?.es

Updated by shevegen (Robert A. Heiler) about 4 years ago

This is not a good feature request, IMO.

There is not really any explanation as to what the idea is about. Why is
p pid and s existatus suddenly? And why should that be common if one
can already extend these classes as-is? What is the rationale for the
feature request? Even IF this were accepted as-is, I think there should
be a fair description of the issue request, so that other people can
understand what is going on at a later point in time. This would be
more in line what is often encouraged for people to do by the ruby
core team, in that they should describe (possible) use cases, benefits
and drawbacks objectively.

Actions #2

Updated by 0x81000000 (/ /) about 4 years ago

  • Description updated (diff)
  • Subject changed from Shortcuts for attributes of Process::Status to Shortcut for Process::Status.exitstatus

Updated by Dan0042 (Daniel DeLorme) about 4 years ago

Those short aliases are definitely a bad idea but I understand the OP's frustration with $? because it's different from the shell's $?. Process::Status has several methods that I'm sure can be useful in various circumstances, but the only one I've ever needed was exitstatus. It's a bit irritating when you have to write the verbose $?.exitstatus (get the exit status of the exit status?) instead of the shorter and more natural $?, especially for the common case of exit $?

Updated by nobu (Nobuyoshi Nakada) about 4 years ago

It is not a good idea to compare exitstatus with 0 from the point of portability.
I'd recommend to use Process::Status#success?.
Also if the exit code value is not important but succeeded or failed is just needed, exit $?.success? would be enough.
Even exec works better than system & exit, unless you need some clean-ups.

Updated by 0x81000000 (/ /) almost 4 years ago

nobu (Nobuyoshi Nakada) wrote in #note-4:

Even exec works better than system & exit, unless you need some clean-ups.

You're right. What can you say about this 'vararg require':

module Kernel
    alias :require_1 :require
    def require p, *a
        return require_1 p if a.empty?
        a.unshift p
        a.map { | s | require_1 s }
    end
end

Could this break backward compatibility?

Updated by Dan0042 (Daniel DeLorme) almost 4 years ago

nobu (Nobuyoshi Nakada) wrote in #note-4:

It is not a good idea to compare exitstatus with 0 from the point of portability.

Can I ask why that is? 0 is success and non-0 is failure; I don't know of any system where things are different. What is the portability issue?

Even exec works better than system & exit, unless you need some clean-ups.

exec only works as a tail-call at the end of the script. Most of the time it's not applicable:

system(cmd1) or exit($?.exitstatus)
system(cmd2) or exit($?.exitstatus)
system(cmd3) or exit($?.exitstatus)

Although thanks to your comment I've realized that exitstatus is nil if the process exited because of a signal. That means the code above is equivalent to exit(0) if the command failed because of $?.signaled? :-(
I guess I'm better off sticking with system(cmd1) or abort

Updated by nobu (Nobuyoshi Nakada) almost 4 years ago

Dan0042 (Daniel DeLorme) wrote in #note-6:

nobu (Nobuyoshi Nakada) wrote in #note-4:

It is not a good idea to compare exitstatus with 0 from the point of portability.

Can I ask why that is? 0 is success and non-0 is failure; I don't know of any system where things are different. What is the portability issue?

I don't know such systems actually too, just only the rationale of EXIT_SUCCESS and EXIT_FAILURE in the C standard.

Although thanks to your comment I've realized that exitstatus is nil if the process exited because of a signal. That means the code above is equivalent to exit(0) if the command failed because of $?.signaled? :-(

That executes exit(nil) and results in TypeError.

I guess I'm better off sticking with system(cmd1) or abort

Yes, it's a good alternative.

It may be acceptable to let exit accept a SystemExit instance though.

Updated by Eregon (Benoit Daloze) almost 4 years ago

nobu (Nobuyoshi Nakada) wrote in #note-7:

It may be acceptable to let exit accept a SystemExit instance though.

I think that would be useful.
I'd guess it would behave as something like:

# useful if terminated by a signal:
exit(status) =>
exit(status.exitstatus || status.termsig || status.stopsig || 1)

# or maybe the simpler
exit(status) =>
exit(status.exitstatus || 1)
# but then no information if terminated by signal, which is bad

It's probably even better to raise a SignalException on exit(status) if status.signaled?, that way the information is completely forwarded to the parent process.

Updated by 0x81000000 (/ /) almost 4 years ago

Dan0042 (Daniel DeLorme) wrote in #note-6:

exec only works as a tail-call at the end of the script. Most of the time it's not applicable:

system(cmd1) or exit($?.exitstatus)
system(cmd2) or exit($?.exitstatus)
system(cmd3) or exit($?.exitstatus)
exec 'cmd1 && cmd2 && cmd3'

Updated by Dan0042 (Daniel DeLorme) almost 4 years ago

nobu (Nobuyoshi Nakada) wrote in #note-7:

That executes exit(nil) and results in TypeError.

Ah, interesting, I was testing in irb where exit(nil) was equivalent to exit(0)

Eregon (Benoit Daloze) wrote in #note-8:

nobu (Nobuyoshi Nakada) wrote in #note-7:

It may be acceptable to let exit accept a SystemExit instance though.

I think that would be useful.
I'd guess it would behave as something like:

# useful if terminated by a signal:
exit(status) =>
exit(status.exitstatus || status.termsig || status.stopsig || 1)

Are we talking about SystemExit or Process::Status? I don't understand how SystemExit would work or be useful here, but I love the idea of exit($?) serving as a shortcut for that long expression. Actually it seems that a signal-terminated process has an exit status of 128+signal in the shell. So exit($?) could be a shortcut for exit($?.exitstatus || 128 + ($?.termsig || $?.stopsig || 0)). I think there's a real win in having the easier to use shorter expression be more robust/correct than the longer exit($?.exitstatus)

It's probably even better to raise a SignalException on exit(status) if status.signaled?, that way the information is completely forwarded to the parent process.

Maybe... but honestly I'm not sure it would be architecturally correct for the process to fake being terminated by a signal. Also what would happen if the process was catching the signal that caused the subprocess to terminate? It seems simpler and less edge-case-prone to let the exit method do a regular exit.

trap("PIPE"){ }
system("cmd1") or #terminated by PIPE
  exit($?)        #does not exit because of trap?
#we reach here even though cmd1 failed?
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0