[RCR/BUG?] fix system

A

Ara.T.Howard

this seems broken:

~/tmp > cat a.rb
STDERR.reopen STDOUT
STDOUT.sync
DIV = '=' * 79

commands = [
'no-such-command',
'ls --no-such-option',
'ls .',
]

commands.each do |command|
[false, true].each do |redirect|
fork do
puts DIV

command << " >/dev/null 2>&1" if redirect

puts "command <#{ command }>"

system command

puts "exit_status <#{ $?.exitstatus }>"
end
Process.wait
end
end

~/tmp > ruby a.rb
===============================================================================
command <no-such-command>
a.rb:18:in `system': No such file or directory - no-such-command (Errno::ENOENT)
from a.rb:18
from a.rb:13:in `fork'
from a.rb:13
from a.rb:13:in `each'
from a.rb:12
from a.rb:12:in `each'
from a.rb:11
from a.rb:11
===============================================================================
command <no-such-command >/dev/null 2>&1>
exit_status <127>
===============================================================================
command <ls --no-such-option>
ls: unrecognized option `--no-such-option'
Try `ls --help' for more information.
exit_status <1>
===============================================================================
command <ls --no-such-option >/dev/null 2>&1>
exit_status <1>
===============================================================================
command <ls .>
a.rb
exit_status <0>
===============================================================================
command <ls . >/dev/null 2>&1>
exit_status <0>


the above behaviour of system means the following rules must be followed when
making system calls:

- iff stderr IS NOT redirected you must be prepared to catch Errno::ENOENT in
the event your command is not found.

- iff stderr IS redirected you will NOT be informed of non-existent commands
via an exception and must check $?.exitstatus manually for 127 to
determine if the command was not found

- in all cases you must check $?.exitstatus for success since your command
may be found, but fail for other reasons and this will not raise any
errors.

so, in summary you must still always check $?, but sometimes errors will be
thrown depending on the contents of the string passed to system. am i the
only one who finds this confusing? it seems like any code using system will
turn into spaghetti if it follows these rules...

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
A

Andrew Walrond

so, in summary you must still always check $?, but sometimes errors will be
thrown depending on the contents of the string passed to system. am i the
only one who finds this confusing? it seems like any code using system
will turn into spaghetti if it follows these rules...

Oh dear...

Is this a snapshot?
 
A

Ara.T.Howard

Oh dear...

Is this a snapshot?

yes.

~/build/ruby > ruby -v
ruby 1.9.0 (2004-05-27) [i686-linux]


-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
Y

Yukihiro Matsumoto

Hi,

In message "[RCR/BUG?] fix system"

|the above behaviour of system means the following rules must be followed when
|making system calls:

If you put the shell special characters ("*?{}[]<>()~&|\\$;'`\"\n") in
the command string, system() will prepend "sh -c" to the command string,
so that

no-such-command

was interpreted as

sh -c no-such-command

that explains the behavior.

matz.
 
A

Andrew Walrond

If you put the shell special characters ("*?{}[]<>()~&|\\$;'`\"\n") in
the command string, system() will prepend "sh -c" to the command string,
so that

that explains the behavior.

Should have remembered that :)
But the throwing exceptions thing is still new, as discussed in another
thread.

Andrew
 
A

Ara.T.Howard

Hi,

In message "[RCR/BUG?] fix system"

|the above behaviour of system means the following rules must be followed when
|making system calls:

If you put the shell special characters ("*?{}[]<>()~&|\\$;'`\"\n") in
the command string, system() will prepend "sh -c" to the command string,
so that

no-such-command

was interpreted as

sh -c no-such-command

that explains the behavior.

matz.

yes it does... i guess it's just a little odd when combined with the
exception throwing through... so, the reccomended policy is to be prepared to
deal with both exceptions and $? - correct?

cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
N

nobu.nokada

Hi,

At Wed, 30 Jun 2004 02:22:54 +0900,
Ara.T.Howard wrote in [ruby-talk:104856]:
- iff stderr IS NOT redirected you must be prepared to catch Errno::ENOENT in
the event your command is not found.

- iff stderr IS redirected you will NOT be informed of non-existent commands
via an exception and must check $?.exitstatus manually for 127 to
determine if the command was not found

Even with stdin or stdout. And you should remember that
redirecting stderr is not portable.
- in all cases you must check $?.exitstatus for success since your command
may be found, but fail for other reasons and this will not raise any
errors.

Kernel#system returns true when the command succeeded, or false.

One thought:
system could return nil keeping error info when the command
couldn't execute, as perl does. Then, the current behavior
would moved to Process.start, invoke or something else.
 
A

Ara.T.Howard

Kernel#system returns true when the command succeeded, or false.

One thought:
system could return nil keeping error info when the command
couldn't execute, as perl does. Then, the current behavior
would moved to Process.start, invoke or something else.

i like this. i use this sort of thing alot

ret = method

case ret
when true
when false
when nil
end

but some might not like it. i think it's clean since it still allows

system cmd or abort "failed on <#{ cmd }>"


i just have a feeling that combination of exception and exitstatus checking
will suprise many. although i admit the separation dose make logical sense
to me now...

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
N

nobu.nokada

Hi,

At Wed, 30 Jun 2004 11:22:54 +0900,
Ara.T.Howard wrote in [ruby-talk:104891]:
i like this. i use this sort of thing alot

I noticed that I've forgotten to send this patch. This
separates Kernel#system and Process#system, the former behaves
as older version and the latter does as current version. The
name is provisional.


Index: process.c
===================================================================
RCS file: /cvs/ruby/src/ruby/process.c,v
retrieving revision 1.107
diff -U2 -p -d -r1.107 process.c
--- process.c 29 Jun 2004 01:17:39 -0000 1.107
+++ process.c 1 Jul 2004 02:04:36 -0000
@@ -1575,5 +1575,5 @@ rb_spawn(argc, argv)
/*
* call-seq:
- * system(cmd [, arg, ...]) => true or false
+ * Process.system(cmd [, arg, ...]) => true or false
*
* Executes _cmd_ in a subshell, returning +true+ if the command ran
@@ -1592,5 +1592,5 @@ rb_spawn(argc, argv)

static VALUE
-rb_f_system(argc, argv)
+rb_proc_system(argc, argv)
int argc;
VALUE *argv;
@@ -1610,4 +1610,37 @@ rb_f_system(argc, argv)
/*
* call-seq:
+ * system(cmd [, arg, ...]) => true, false or nil
+ *
+ * Same as <code>Process.system</code> except for no exception raise
+ * but nil is returned.
+ */
+
+static VALUE
+rb_f_system(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ int status;
+
+ status = rb_spawn(argc, argv);
+ if (status == -1) {
+ VALUE args[2], e;
+ args[0] = argv[0];
+ args[1] = INT2FIX(errno);
+ e = rb_class_new_instance(2, args, rb_eSystemCallError);
+ rb_warning("failed to execute: %s", RSTRING(rb_obj_as_string(e))->ptr);
+ ruby_errinfo = e;
+ return Qnil;
+ }
+#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
+ rb_syswait(status);
+ status = NUM2INT(rb_last_status);
+#endif
+ if (status == EXIT_SUCCESS) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * call-seq:
* spawn(cmd [, arg, ...]) => pid
*
@@ -3472,4 +3505,5 @@ Init_process()

rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
+ rb_define_singleton_method(rb_mProcess, "system", rb_proc_system, -1);
rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

ANN main-4.4.0 0
[ANN] main-4.0.0 (for avdi) 0
[ANN] main-2.8.3 2
[ANN] main-3.0.1 0
[ANN] main-0.0.2 5
[ANN] main-2.6.0 0
[ANN] main-2.1.0 6
[ANN] main-2.5.0 4

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,268
Latest member
AshliMacin

Latest Threads

Top