Forum: Ruby Spawning

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.
Steve L. (Guest)
on 2005-12-18 06:56
(Received via mailing list)
Hi all,

My umenu program has a utility called ufork.pl, whose job it is to
run an X program in the background in such a way that even if the
process that ran it is killed, the X program continues to live. I
want to translate it to Ruby, but I can't find an equivalent to
Perl's setsid anywhere in the Kernel module. Here's the code:

#!/usr/bin/perl -w
use strict;

use POSIX qw(setsid);

sub launch(@) {
    my(@args) = @_;
    unless (fork) {
        setsid;             # set child process to new session
        unless (fork) {     # Create a grandchild
            close STDIN;    # close std files
            close STDOUT;
            close STDERR;
            exec @args;     # exec the x program
        }
    }
    sleep(1);
}

launch(@ARGV);

=======================

Anyone know an equivalent to setsid? Anyone ever do this in Ruby
before? I think it's a fairly common riff.

Thanks

SteveT
James G. (Guest)
on 2005-12-18 07:11
(Received via mailing list)
On Dec 17, 2005, at 10:56 PM, Steve L. wrote:

> I want to translate it to Ruby, but I can't find an equivalent to
> Perl's setsid anywhere in the Kernel module.

I believe you are looking for Process.setsid.

   ri Process.setsid

James Edward G. II
Steve L. (Guest)
on 2005-12-18 07:38
(Received via mailing list)
On Sunday 18 December 2005 12:09 am, James Edward G. II wrote:
> On Dec 17, 2005, at 10:56 PM, Steve L. wrote:
> > I want to translate it to Ruby, but I can't find an equivalent
> > to Perl's setsid anywhere in the Kernel module.
>
> I believe you are looking for Process.setsid.
>
>    ri Process.setsid
>
> James Edward G. II

Thanks James.

That works! I can run it from a terminal, close the terminal, and
the spawned program containues running. This is the exact behavior
I need. However...

I have one other problem. Somehow I cannot use exec on my array of
arguments -- only on the very first one (the program name). This
means I can't pass arguments to the spawned program.

See here:

#!/usr/bin/ruby -w


def launch(argarray)
	unless (fork)
		Process::setsid    # set child process to new session
		unless (fork)      # Create a grandchild
			STDIN.close    # close std files
			STDOUT.close
			STDERR.close
			#exec argarray  ## This doesn't run the program
			command = argarray.shift
			exec command
			# exec command, argarray ## Doesn't run pgm
			# exec command, argarray[0], argarray[1]  ## no run pgm
		end
	end
	sleep(1)
end # launch()

launch(ARGV)
Steve L. (Guest)
on 2005-12-18 08:02
(Received via mailing list)
On Sunday 18 December 2005 12:36 am, Steve L. wrote:
>
> Thanks James.
>
> That works! I can run it from a terminal, close the terminal, and
> the spawned program containues running. This is the exact
> behavior I need. However...
>
> I have one other problem. Somehow I cannot use exec on my array
> of arguments -- only on the very first one (the program name).
> This means I can't pass arguments to the spawned program.

I got it to work with a kludge:

exec argarray.join(' ')

I converted the array of arguments to a string, and it worked. But
it should have worked the other way too. What am I missing?

SteveT



Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid
Florian F. (Guest)
on 2005-12-18 11:48
(Received via mailing list)
Steve L. wrote:

>I converted the array of arguments to a string, and it worked. But
>it should have worked the other way too. What am I missing?
>
>
exec *argarray
Steve L. (Guest)
on 2005-12-18 14:45
(Received via mailing list)
On Sunday 18 December 2005 04:46 am, Florian F. wrote:
> Steve L. wrote:
> >I converted the array of arguments to a string, and it worked.
> > But it should have worked the other way too. What am I missing?
>
> exec *argarray

Confirmed! Thanks Florian.

Now I can run a command with several words quoted together to make
one argument.

Curious -- what does the asterisk do to make it work when it didn't
work without the asterisk. What does the asterisk do? I know it
doesn't mean "the contents of this address" -- that's another
language :-)

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid
Stefan L. (Guest)
on 2005-12-18 15:00
(Received via mailing list)
On Sunday 18 December 2005 13:43, Steve L. wrote:
> one argument.
>
> Curious -- what does the asterisk do to make it work when it didn't
> work without the asterisk. What does the asterisk do? I know it
> doesn't mean "the contents of this address" -- that's another
> language :-)

It flattens the array (argarray) into an argument list.
This means the first element of argarray becomes the first
argument to exec, the second element of argarray becomes
the second argument to exec and so on.

The following irb session demonstrates this:
##########################################################
irb(main):001:0> def m(arg1 = nil, arg2 = nil, arg3 = nil)
irb(main):002:1>   p arg1
irb(main):003:1>   p arg2
irb(main):004:1>   p arg3
irb(main):005:1> end
=> nil
irb(main):006:0> m
nil
nil
nil
=> nil
irb(main):007:0> m(1, 2, 3)
1
2
3
=> nil
irb(main):008:0> ary = [1, 2, 3]
=> [1, 2, 3]
irb(main):010:0> m(ary)
[1, 2, 3]
nil
nil
=> nil
irb(main):011:0> m(*ary)
1
2
3
=> nil
irb(main):012:0> ary = [1, 2]
=> [1, 2]
irb(main):013:0> m(ary)
[1, 2]
nil
nil
=> nil
irb(main):014:0> m(*ary)
1
2
nil
=> nil

Regards,
  Stefan
This topic is locked and can not be replied to.