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.
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 Steve Litt (Guest)
on 2005-12-18 05: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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2005-12-18 06:11
(Received via mailing list)
On Dec 17, 2005, at 10:56 PM, Steve Litt 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 Gray II
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 Steve Litt (Guest)
on 2005-12-18 06:38
(Received via mailing list)
On Sunday 18 December 2005 12:09 am, James Edward Gray II wrote:
> On Dec 17, 2005, at 10:56 PM, Steve Litt 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 Gray 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)
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 Steve Litt (Guest)
on 2005-12-18 07:02
(Received via mailing list)
On Sunday 18 December 2005 12:36 am, Steve Litt 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 Litt
http://www.troubleshooters.com
slitt@troubleshooters.com
D84df7c68f790e492c4ad4ec5fe65547?d=identicon&s=25 Florian Frank (Guest)
on 2005-12-18 10:48
(Received via mailing list)
Steve Litt 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
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 Steve Litt (Guest)
on 2005-12-18 13:45
(Received via mailing list)
On Sunday 18 December 2005 04:46 am, Florian Frank wrote:
> Steve Litt 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 Litt
http://www.troubleshooters.com
slitt@troubleshooters.com
2d532341317628fbb2cb22ec427a1d62?d=identicon&s=25 Stefan Lang (Guest)
on 2005-12-18 14:00
(Received via mailing list)
On Sunday 18 December 2005 13:43, Steve Litt 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.