Spawning

S

Steve Litt

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
 
S

Steve Litt

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)
 
S

Steve Litt

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
(e-mail address removed)
 
F

Florian Frank

Steve said:
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
 
S

Steve Litt

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
(e-mail address removed)
 
S

Stefan Lang

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 :)

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
 
L

Logan Capaldo

I've seen it also called the 'splat' operator, and (I think?) David
Black called it the 'unary unarray' operator, which I a good name
for it. It doesn't just work with method arguments, and it doesn't
just work with arrays:

p = *File.open('/etc/passwd')

gives an array of all the lines in the file. I was most impressed
when I found that out recently ;)

(p.s. I'm not advocating that method of reading files _at all_ -
it's just an example)

This scared me, so I did some experiments
logan:/Users/logan% irb
irb(main):001:0> lines = *File.open('test.yml')
=> ["---\n", "words:\n", " - yes\n", " - put\n", " - it\n", " - on
\n", " - the\n", " - off\n", " - setting\n"]
irb(main):002:0> h = { :a=>:b, :c=>:d }
=> {:a=>:b, :c=>:d}
irb(main):003:0> keysvals = *h
=> [[:a, :b], [:c, :d]]
irb(main):004:0> class Q
irb(main):005:1> def to_a
irb(main):006:2> "Hello!"
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> q = Q.new
=> #<Q:0xc13e4>
irb(main):010:0> qarray = *q
TypeError: `to_a' did not return Array
from (irb):10
from :0
irb(main):011:0>

Apparently splat will splat almost anything as long as its to_a
method returns an array (a reasonable assumption). I don't know if I
really like this. I always kind of thought of splat as syntax (like
&), not really as a method (operator). Apparently its not the unary
unarray operator, its the unary to array then unarray operator.
 
J

James Edward Gray II

Ok. I was unaware of that. But to_proc is more like to_ary than
to_a, IMO. (Not that I've ever seen a to_p ;) ). I could maybe go
for splat working on anything that responded to to_ary, but
currently it just personally feels kinda icky.

Wish granted. ;)
class ToAry
undef to_a
def to_ary
[1, 2, 3]
end
end => nil
arr = ToAry.new
=> # said:
arr.respond_to? :to_a => false
def show( one, two, three )
p one
p two
p three
end => nil
show(*arr)
1
2
3
=> nil

to_ary() is favored. Otherwise, to_a() is used.

James Edward Gray II
 
L

Logan Capaldo

Wish granted. ;)
[snip example code]
to_ary() is favored. Otherwise, to_a() is used.

James Edward Gray II

Well my real wish was that the otherwise didn't exist but I takes
whats I can gets I suppose. If it really bothers me I'll just switch
to Java or Python. Those languages match my exact ideals of how splat
and & should work. (kidding)
 

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

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top