[29970] in Perl-Users-Digest
Perl-Users Digest, Issue: 1213 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Jan 18 21:09:44 2008
Date: Fri, 18 Jan 2008 18:09:11 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Fri, 18 Jan 2008 Volume: 11 Number: 1213
Today's topics:
Can't Install Perl as Non-Root <Dawmail333@gmail.com>
Re: Client Program not Receiving Message from Server <deadpickle@gmail.com>
perl -pe substitution <asuter@cisco.com>
Re: perl -pe substitution <abigail@abigail.be>
Re: pop up to capture user and password <glex_no-spam@qwest-spam-no.invalid>
Re: pop up to capture user and password burrell.john@yahoo.com
Re: Wait for background processes to complete <hjp-usenet2@hjp.at>
Re: Wait for background processes to complete <hjp-usenet2@hjp.at>
Re: Wait for background processes to complete <ced@blv-sam-01.ca.boeing.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Fri, 18 Jan 2008 15:44:00 -0800 (PST)
From: dawmail333 <Dawmail333@gmail.com>
Subject: Can't Install Perl as Non-Root
Message-Id: <19f4e7cb-1284-4333-96fa-d896faa970c4@1g2000hsl.googlegroups.com>
Hi!
I was trying to install a personal version of Perl to my own user
folder. I am running on a remote webserver that uses Apache. I have
succeeded with the following steps:
wget http://perl.com/CPAN/src/stable.tar.gz
tar zvxf stable.tar.gz
cd perl-5.8.8
sh Configure -de -Dprefix=/home/.bazooka/dawliam/perl/
This is the line I encounter problems on:
make && make test && make install
This is the 'dump':
Extracting find2perl (with variable substitutions)
make[1]: Leaving directory `/home/.bazooka/dawliam/perl-5.8.8/x2p'
Making B (dynamic)
opendir(./../../../../..): Permission denied at ../../lib/File/Find.pm
line 604
Use of chdir('') or chdir(undef) as chdir() is deprecated at ../../lib/
File/Find
.pm line 751.
opendir(./../..): Permission denied at ../../lib/ExtUtils/MakeMaker.pm
line 170
Couldn't change to directory /home/.bazooka/dawliam/C: No such file or
directory
at Makefile.PL line 18
Writing Makefile for B
Warning: No Makefile!
make[1]: Entering directory `/home/.bazooka/dawliam/perl-5.8.8/ext/B'
make[1]: *** No rule to make target `config'. Stop.
make[1]: Leaving directory `/home/.bazooka/dawliam/perl-5.8.8/ext/B'
make config failed, continuing anyway...
make[1]: Entering directory `/home/.bazooka/dawliam/perl-5.8.8/ext/B'
make[1]: *** No rule to make target `all'. Stop.
make[1]: Leaving directory `/home/.bazooka/dawliam/perl-5.8.8/ext/B'
make: *** [lib/auto/B/B.so] Error 2
[hyperion]$ /home/.bazooka/dawliam/perl -MCPAN -e shell
-bash: /home/.bazooka/dawliam/perl: is a directory
[hyperion]$
Can anyone help? Thanks in advance.
------------------------------
Date: Fri, 18 Jan 2008 16:42:07 -0800 (PST)
From: deadpickle <deadpickle@gmail.com>
Subject: Re: Client Program not Receiving Message from Server
Message-Id: <9e039fe6-624f-49db-b81a-461625b2042e@s8g2000prg.googlegroups.com>
On Jan 18, 11:27 am, deadpickle <deadpic...@gmail.com> wrote:
> My chat client/server program does not seem to be receiving messages.
> It utilizes a Glib::Timeout to loop a sub named wait_for_msg that
> listen for the server to send the message so that it can be received
> and displayed in the Textview widget. The program connects to the
> server fine, logs in great. When the user types in the entry box and
> hits send, the program sends the entered message to the server and it
> is then sent to all clients including the author of the message. The
> problem is that the client is not receiving the message from the
> server; I suspect it is the timer. I tried printing text in the loop
> to see if it was still running but it only printed once which could
> mean that it has stopped working. Any ideas on how to remedy this
> problem?
>
> #!/usr/bin/perl
> # Flow of the Program:
> # *Send message to the server - send_msg_all
> # *Connect to the server - sub connect_server
> # -unblock the server - nonblock
> # -Login to the server - send_login
> # -Timer started to wait for messages - wait_for_msg
> # >Handler - handle
> # $Process the incoming messages - process_incoming
> # @Recieve messages and display in textview - rcv_msg_all
>
> use warnings;
> use strict;
> use Gtk2 -init;
> use Glib qw/TRUE FALSE/;
> use IO::Socket::INET;
> use Tie::RefHash;
> use IO::Select;
>
> #global variables
> my $buffer;
> my $host = "Deadpickle-hobo";
> my $port = 6666;
> my $conn_stat = 'idle';
> my %inbuffer = ();
> my %outbuffer = ();
> my %ready = ();
> my $select;
> my $conn;
> my $user;
>
> #the main chat widget
> my $main_window = Gtk2::Window->new("toplevel");
> $main_window->signal_connect(delete_event => sub {Gtk2->main_quit;});
> $main_window->set_default_size(250, 200);
>
> my $table = Gtk2::Table->new(4, 2, FALSE);
>
> $buffer = Gtk2::TextBuffer->new;
> my $button = Gtk2::Button->new("Send");
> my $entry = Gtk2::Entry->new();
>
> my $label = Gtk2::Label->new("Chat Client Test");
>
> my $textview = Gtk2::TextView->new_with_buffer($buffer);
> $textview->set_cursor_visible (FALSE);
> my $swindow = Gtk2::ScrolledWindow->new( undef, undef);
> $swindow->set_policy( 'automatic', 'automatic');
> $swindow->set_shadow_type( 'etched-out');
>
> $swindow->add( $textview);
>
> $table->attach_defaults($label, 0, 1, 0, 1);
> $table->attach_defaults($swindow, 0, 2, 1, 3);
> $table->attach_defaults($entry, 0, 1, 3, 4);
> $table->attach_defaults($button, 1, 2, 3, 4);
> $main_window->add($table);
>
> $main_window->show_all();
>
> $button->signal_connect("clicked" => sub { send_msg_all($entry-
>
> >get_text); $entry->set_text('');} );
>
> #run the login dialog
> dialog($buffer);
>
> Gtk2->main;
>
> #-------------------Login Dialog-------------------
> sub dialog{
> my $buffer = shift;
>
> my $dialog_window = Gtk2::Window->new('toplevel');
> $dialog_window->signal_connect(delete_event => sub {Gtk2-
>
> >main_quit});
>
> my $dialog_table = Gtk2::Table->new(2, 2, FALSE);
> my $dialog_label1 = Gtk2::Label->new('Chat Login:');
> my $dialog_label2 = Gtk2::Label->new('User:');
> my $dialog_label3 = Gtk2::Label->new('Host:');
> my $chat_user = Gtk2::Entry->new();
> $chat_user->set_text('');
> my $dialog_button1 = Gtk2::Button->new('Connect');
>
> $dialog_table->attach_defaults($dialog_label1, 0, 1, 0, 1);
> $dialog_table->attach_defaults($chat_user, 1, 2, 0, 1);
> $dialog_table->attach_defaults($dialog_button1, 1, 2, 1, 2);
>
> $dialog_button1->signal_connect("clicked" => sub {$user = $chat_user-
>
> >get_text; $dialog_window->destroy; $buffer->insert(($buffer-
> >get_end_iter), "Username: $user...\n"); connect_server()});
>
> $dialog_window->add($dialog_table);
>
> $dialog_window->show_all;
>
> return 1;}
>
> #------------------Connect to server---------------------
> #establishes connection to the server
> sub connect_server{
> if ($conn_stat ne 'connected') {
> $buffer->insert(($buffer->get_end_iter), "Connecting to Server
> $host:$port...\n");
>
> $conn = IO::Socket::INET->new(PeerAddr => $host, PeerPort =>
> $port, Proto => 'tcp') or popup_err(1);
>
> if ($conn) {
> %inbuffer = ();
> %outbuffer = ();
> %ready = ();
> tie %ready, 'Tie::RefHash';
> nonblock($conn);
> $select = IO::Select->new($conn);
> $conn_stat = 'connected';
> $buffer->insert(($buffer->get_end_iter), "Connected!\n");
>
> #send login to server
> send_login();
>
> #start the timer that monitors incoming messages
> my $timer_waiting = Glib::Timeout->add(100, \&wait_for_msg);
> }
> }}
>
> #-------------------Error popup-------------------
> # pops up an error message
> sub popup_err{
> my ($error_code) = @_;
> my $error;
>
> if ($error_code == 1) {$error = "Cannot create Socket!"}
> elsif ($error_code == 2) {$error = "Username to Short!"}
> elsif ($error_code == 3) {$error = "No connection Established!"}
> elsif ($error_code == 4) {$error = "Already Logged on with This User
> Name!"}
> elsif ($error_code == 5) {$error = "Not Connected!"}
> else {$error = "Unkown Error!"}
>
> $buffer->insert(($buffer->get_end_iter), "$error\n");
>
> my $error_dialog = Gtk2::MessageDialog->new($main_window, 'destroy-
> with-parent', 'error', 'ok', "$error");
>
> $error_dialog->run;
> $error_dialog->destroy;}
>
> #-------------------blocking-------------------
> # nonblock($socket) puts socket into nonblocking mode
> sub nonblock { my $socket = shift; $socket->blocking(0);}
> #-------------------Message Waiting-------------------
> # Wait for incoming messages from the server relayed from clients
> sub wait_for_msg {
>
> if ($conn_stat eq 'connected') {
> my ($list_size, $msg);
> my $server;
> my $rv;
> my $data;
>
> print "waiting..\n";
>
> # check for new information on the connections we have
> # anything to read or accept?
> foreach $server ($select->can_read(1)) {
> # read data
> $data = '';
> $rv = $server->recv($data, 'POSIX::BUFSIZ', 0);
> $inbuffer{$server} .= $data;
>
> # test whether the data in the buffer or the data we
> # just read means there is a complete request waiting
> # to be fulfilled. If there is, set $ready{$client}
> # to the requests waiting to be fulfilled.
> while ($inbuffer{$server} =~ s/(.*\n)//) {
>
> push( @{$ready{$server}}, $1 );
> }
> }
>
> # Any complete requests to process?
> foreach $server (keys %ready) {
>
> handle($server);
> }
> }}
>
> #-------------------Handler-------------------
> # handle($socket) deals with all pending requests for $client
> sub handle {
> # requests are in $ready{$server}
> # send output to $outbuffer{$server}
> my $server = shift;
> my $request;
>
> print "HANDLER WORKING\n";
>
> foreach $request (@{$ready{$server}}) {
> # $request is the text of the request
> # put text of reply into $outbuffer{$client}
> chomp $request;
> process_incoming($server, $request);
> }
> delete $ready{$server};}
>
> #-------------------Process Incoming-------------------
> sub process_incoming {
> my ($server, $msg) = @_;
> my @logged_users;
> my @rcvd_msg = split(/::/, $msg);
>
> if ($rcvd_msg[1] eq "1") {
> if($rcvd_msg[2] eq "03") {
> print "Successfully Logged in!\n";
> } elsif ($rcvd_msg[2] eq "12") {
> popup_err(4);
> } else {
> # Create pop-up for error!
> print "Error Logging in ", $msg, "\n";
> popup_err(5);
> }
> }
> elsif ($rcvd_msg[1] eq "7") {
> # receive global message
> print "$msg\n";
> rcv_msg_all($rcvd_msg[3], $rcvd_msg[4
> } else {
> print "Unrecognized response: $msg\n";
> exit(0);
> }}
>
> #-------------------Send message to all-------------------
> sub send_msg_all {
> my ($msg) = @_;
>
> print "$conn\n";
>
> if(defined $conn) {
> # Send a the Message to server
> print "Sending\n";
> print $conn "7\:\:$user\:\:$msg\n";
> } else {
> popup_err(3);
> }}
>
> #-------------------Send login-------------------
> #logs the user name on the server
> sub send_login {
> # my ($u) = @_;
>
> if(defined $conn) {
> if(length($user) > 0) {
> #send login to server
> print $conn "1\:\:$user\n";
> # update_info();
> } else {
> popup_err(2);
> }
> } else {
> popup_err(3);
> }}
>
> #-------------------Display All Message-------------------
> sub rcv_msg_all {
> my ($from, $msg) = @_;
>
> print "Received Global message:\n";
> if(defined $conn) {
> print "Already Connected: Proceeding with message!\n";
> $buffer->insert(($buffer->get_end_iter), "$from: $msg\n");
> } else {
> print "No connection established!\n";
> popup_err(3);
> }
>
> }
taking the advice I added "return 1" to the end of the subroutines.
The prints in the rcv_msg_all and handle subroutines are not printing
in the terminal so it makes me wounder whether they are actually
running at all. I'm still not receiving any messages into the client
and I cant seem to see why. Course I missed adding "return 1" to the
subs so its probably right in front of me.
------------------------------
Date: Fri, 18 Jan 2008 14:43:22 -0800
From: "Asim Suter" <asuter@cisco.com>
Subject: perl -pe substitution
Message-Id: <1200696203.76315@sj-nntpcache-3.cisco.com>
Case 1)
my $VAR = 'ABC@VERSION@DEF' ;
$VAR =~ s/\@VERSION\@/1.2.3.4/g ;
print "<$VAR>\n" ;
Prints <ABC1.2.3.4DEF> as expected.
=========================
Case 2)
Lets say $input_file has a line containing ABC@VERSION@DEF
And I want to replace @VERSION@ by 1.2.3.4 So I do:
`perl -pe 's/\@VERSION\@/1.2.3.4/g' -i $input_file` ;
Which chnages the content in $input_file to
ABC1.2.3.4VERSION1.2.3.4DEF
Why the difference in the two cases ?
What do I need to do to get bahavior like Case 1 in Case 2 ?
I'd suspect some special interpretation of @ at play but it's escaped - but
not sure any ideas ?
Thanks!
------------------------------
Date: 18 Jan 2008 22:57:11 GMT
From: Abigail <abigail@abigail.be>
Subject: Re: perl -pe substitution
Message-Id: <slrnfp2bm7.gm.abigail@alexandra.abigail.be>
_
Asim Suter (asuter@cisco.com) wrote on VCCLIII September MCMXCIII in
<URL:news:1200696203.76315@sj-nntpcache-3.cisco.com>:
``
``
`` Case 1)
``
`` my $VAR = 'ABC@VERSION@DEF' ;
``
`` $VAR =~ s/\@VERSION\@/1.2.3.4/g ;
``
`` print "<$VAR>\n" ;
``
``
``
`` Prints <ABC1.2.3.4DEF> as expected.
``
`` =========================
``
`` Case 2)
``
`` Lets say $input_file has a line containing ABC@VERSION@DEF
``
`` And I want to replace @VERSION@ by 1.2.3.4 So I do:
``
`` `perl -pe 's/\@VERSION\@/1.2.3.4/g' -i $input_file` ;
^
|
You have backticks here. Are you calling perl from withing perl?
If so, you're excaping the @ from the *OUTER* perl - that is, the
outer perl sees '@VERSION@', which for the inner perl is the array @VERSION
followed by @. So you would have to write something like:
`perl -pe 's/\\\@VERSION\\\@/1.2.3.4/g' -i $input_file`;
``
`` Which chnages the content in $input_file to
``
`` ABC1.2.3.4VERSION1.2.3.4DEF
``
`` Why the difference in the two cases ?
``
`` What do I need to do to get bahavior like Case 1 in Case 2 ?
``
`` I'd suspect some special interpretation of @ at play but it's escaped - but
`` not sure any ideas ?
You need to escape it for each level of possible interpolation. Which means,
twice in this case.
Abigail
--
sub _ {$_ = shift and y/b-yB-Y/a-yB-Y/ xor !@ _?
exit print :
print and push @_ => shift and goto &{(caller (0)) [3]}}
split // => "KsvQtbuf fbsodpmu\ni flsI " xor & _
------------------------------
Date: Fri, 18 Jan 2008 13:53:19 -0600
From: "J. Gleixner" <glex_no-spam@qwest-spam-no.invalid>
Subject: Re: pop up to capture user and password
Message-Id: <479103b0$0$3580$815e3792@news.qwest.net>
burrell.john@yahoo.com wrote:
[...]
> Actually I think I need to pass the 3 values $MyId, $Name and
> $password like so:
> http://IP/cgi-bin/nextProg.cgi?MyId=123&Name=fred&password=secret
> So I need to work some magic with submit.
Not with submit. See redirect() in perldoc CGI. To muddy the
waters further, you could also look at CGI::Auth which allows
MD5 as an option.
>
> Mr Google seems silent on how to do this.
Really? Then you asked Mr. Google the wrong question.
Maybe you should spend more than 5-minutes with Mr. Google
and start with a CGI tutorial.
> If you help me I will be a happy man - and so will my boss and a
> number of other people...
Sorry, your boss doesn't pay me enough to do your work for you.
------------------------------
Date: Fri, 18 Jan 2008 13:35:07 -0800 (PST)
From: burrell.john@yahoo.com
Subject: Re: pop up to capture user and password
Message-Id: <1c6495ce-5b43-47c8-b718-71b9f72c073e@i7g2000prf.googlegroups.com>
On 18 Jan, 19:53, "J. Gleixner" <glex_no-s...@qwest-spam-no.invalid>
wrote:
> burrell.j...@yahoo.com wrote:
>
> [...]
>
> > Actually I think I need to pass the 3 values $MyId, $Name and
> > $password like so:
> >http://IP/cgi-bin/nextProg.cgi?MyId=3D123&Name=3Dfred&password=3Dsecret
> > So I need to work some magic with submit.
>
> Not with submit. See redirect() in perldoc CGI.
Ta. Will do.
To muddy the
> waters further, you could also look at CGI::Auth which allows
> MD5 as an option.
Sounds good will do..
>
>
>
> > Mr Google seems silent on how to do this.
>
> Really? =A0Then you asked Mr. Google the wrong question.
> Maybe you should spend more than 5-minutes with Mr. Google
> and start with a CGI tutorial.
Actually I think I needed to know about the -sction parameter examples
of which are a bit scarce in tutorials..
>
> > If you help me I will be a happy man - and so will my boss and a
> > number of other people...
>
> Sorry, your boss doesn't pay me enough to do your work for you.
No worries - thanks for your help
------------------------------
Date: Fri, 18 Jan 2008 22:17:15 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: Wait for background processes to complete
Message-Id: <slrnfp25qt.mfv.hjp-usenet2@hrunkner.hjp.at>
On 2008-01-18 17:47, pgodfrin <pgodfrin@gmail.com> wrote:
> This was a lot of fun. I would like to respond to the various
> observations, especially the ones about the Perl Documentation being
> misleading.
[...]
> To restate the original task I wanted to solve:
>
> To be able to execute commands in the background and wait for their
> completion.
>
> The documentation I am referring to is http://perldoc.perl.org/.
>
> If you search on the concept of "background processes" this
> documentation points you to the following in the Language reference >
> perlipc > Background Process :
><begin quote>
> You can run a command in the background with:
>
> system("cmd &");
>
> The command's STDOUT and STDERR (and possibly STDIN, depending on your
> shell) will be the same as the parent's. You won't need
> to catch SIGCHLD because of the double-fork taking place (see below
> for more details).
><end quote>
> There is no further reference to a "double fork" (except in the
> perlfaq8 and only in the context of zombies, which it says are not an
> issue using system("cmd &") ). This is confusing.
I find it more confusing that this seems to be in the section with the
title "Using open() for IPC". I fail to see what one has to do with the
other.
There is a general problem with perl documentation: Perl evolved in the
Unix environment, and a lot of the documentation was written at a time
when the "newbie perl programmer" could be reasonably expected to have
already some programming experience on Unix (in C, most likely) and know
basic Unix concepts like processes, fork(), filehandles, etc. So in a
lot of places the documentation doesn't answer the question "how can I
do X on Unix?" but the question "I already know how to do X in C, now
tell me how I can do it in perl!". When you lern Perl without knowing
Unix first, this can be confusing, because the Perl documentation
generelly explains only Perl, but not Unix.
I am not sure if that should be fixed at all: It's the perl
documentation and not the unix documentation after all, and perl isn't
unix specific, but has been ported to just about every OS.
> The documentation for wait(), waitpid() and fork() do not explain that
> the executing code should be placed in the "child" section of the if
> construct.
Of course not, that would be wrong. There can be code in both (if you
wanted one process to do nothing, why fork?). What the parent should do
and what the child should do depend on what you want them to do. It just
happened that for your particular problem the parent had nothing to do
between forking off children.
> Some of the examples in perlipc show code occurring in both
> the parent and the child section - so it is still not clear. If it
> were, why was I insisting on trying to execute the "cp" command in the
> parent section?
I don't know. What did you expect that would do?
Your problem was:
I want a process to gather a list of files. Then, for each file, it
should start another process which copies the file. These processes
should run in parallel. Finally, it should wait for all these processes
to terminate, and then terminate itself.
Even this description makes it rather implicit, that the original
process creates children and then the children do the copying. If you
add the restriction that a process can only wait for its children, any
other solution becomes extremely awkward.
Besides it is exactly the same what your shell script did: The shell
(the parent process) created child processes in a loop, each child
process executed one cp command, and finally the parent waited for all
the children.
> Furthermore, while the perlipc section is quite verbose, nowhere is
> the code snippet do {$x=wait; print "$x\n"} until $x==-1 or any
> variation of that wait() call mentioned.
Again, this is a solution to your specific problem. You said you wanted
to wait for all children, so Xho wrote a loop which would do that. This
is a rather rare requirement - I think I needed it maybe a handful of
times in 20+ years of programming outside of a child reaper function.
> There are references to a
> while loop and the waitpid() function, but being in the context of a
> signal handler and 'reaping' - it is not clear.
This is the one situation where this construct is frequently used. It
can happen that several children die before the parent can react to the
signal - in this case the reaper function will be called only once, but
it must wait for several children. This isn't obvious, so the docs
mention it.
However, in your case you *know* you started several children and you
*want* to wait for all of them, so it's obvious that you need a loop. This
hasn't anything to do with perl, it's just a requirement of your
problem.
> So, once again many thanks for the help. I would like to know, Peter,
> are you in a position to amend the documentation? Also, the perlfaq8
> does come closer to explaining, but it is simply not clear how the
> fork process will emulate the Unix background operator (&). So how can
> we make this better? How's about this:
fork doesn't "emulate &". fork is one of the functions used by the shell
to execute commands. Basically, the shell does this in a loop:
display the prompt
read the next command
fork
in the child:
execute the command, then exit
in the parent:
if the command did NOT end with &:
wait for the child to terminate
So the Shell always forks before executing commands and it always
executes them in a child process. But normally it waits for the child
process to terminate before displaying the next prompt. If you add the
"&" at the end of the line, it doesn't wait but displays the next prompt
immediately.
(ok, that's a bit too simplistic, but I don't want to go into the arcana
of shell internals here - that would be quite off-topic).
> In the perlipc, under background tasks. make the statement - "the call
> system("cmd &") will run the cmd in the background, but will spawn a
> shell to execute the command, dispatch the command, terminate the
> shell and return to the calling program. The calling program will lose
> the ability to wait for the process as is customary with the shell
> script command 'wait'. In order to both execute one or more programs
> in the background and have the calling program wait for the executions
> to complete it will be necessary to use the fork() function."
I think that would confuse just about anybody who doesn't have exactly
your problem for exactly the same reason you were confused by the
"double fork". It's very specific and should be clear to anyone who
knows what system does and what a unix shell does when you use "&" - I
suspect that sentence about the double fork was added after a discussion
like this one. But I agree that fork should definitely be mentioned here.
system("cmd &") almost never what you would want to do.
> Then in the fork section. Show a simple example like the ones we have
> been working with AND show a simple approach to using the wait
> function.
> Furthermore - add sample code to the wait() and fork()
> functions that are simple and realistic,
fork and wait are very simple building blocks which can be combined in a
lot of different ways. Any sample code here can cover only basic
constructs like
my $pid = fork();
if (!defined $pid) {
die "fork failed: $!";
} elsif ($pid == 0) {
# child does something here
# ...
exit;
} else {
# parent does something here
# ...
# and then waits for child:
waitpid($pid, 0);
}
More complex examples should go into perlipc (which needs serious
cleanup, IMHO).
> unlike the code same in the waitpid() function.
That code is simple and realistic.
> In closing, it is perhaps non-intuitive to me that a fork process
> should have the child section actually executing the code,
If you don't want the child process to do anything, why would you create
it in the first place?
> but I ask you how one can intuit that from the sample in the camel
> book and the samples in the http://perldoc.perl.org/. To really drive
> the point home, Xho's code:
>
> fork or exec("cp $_ $_.old") ;
> do {$x=wait;} until $x==-1 ;
>
> Is STILL not intuitive that the child is executing the code!
True. This code isn't meant to be intuitive. It's meant to be short.
I wouldn't write that in production code, much less in an answer to a
newbie question.
hp
------------------------------
Date: Fri, 18 Jan 2008 22:33:46 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: Wait for background processes to complete
Message-Id: <slrnfp26pr.nfh.hjp-usenet2@hrunkner.hjp.at>
On 2008-01-18 17:30, comp.llang.perl.moderated <ced@blv-sam-01.ca.boeing.com> wrote:
> On Jan 18, 7:11 am, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
>> On 2008-01-18 01:34, comp.llang.perl.moderated <c...@blv-sam-01.ca.boeing.com> wrote:
>>
>>
>>
>> > On Jan 17, 3:12 pm, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
>> >> On 2008-01-17 00:52, comp.llang.perl.moderated <c...@blv-sam-01.ca.boeing.com> wrote:
>>
>> >> > The safest action is an asynchronous wait with a
>>
>> >> Before 5.8.0 that was actually unsafe. But while it is now safe in
>> >> perl
>>
>> > Huh.. just for clarity, here's what I wrote:
>>
>> > use POSIX ":sys_wait_h";
>> > $SIG{CHLD} = \&REAPER;
>> > # now do something that forks...
>> > ...
>> > sub REAPER { 1 while waitpid(-1, WNOHANG)) > 0; }
>>
>> > In fact, historically, there's a clear recommendation to tight-loop
>> > exactly as shown because you may lose signals occurring in
>> > near concurrency if you don't.
>>
>> The problem with this approach is that until 5.8.0 (when "safe signals"
>> were introduced), the REAPER function would be called as soon as the
>> signal arrived regardless of what the perl interpreter was doing at the
>> time - there was a very real risk that this would crash the perl
>> interpreter (in a real world application which forked about 50,000 to
>> 100,000 times a day, the parent process would crash every few days with
>> perl 5.6.0). In C the POSIX standard explicitely states which functions
>> are safe inside a signal handler (and the rest has to be considered
>> unsafe), but for perl no such list existed (so everything has to be
>> considered unsafe). In perl 5.8.0, the "real" signal handler only notes
>> that a signal arrived, and perl will than invoke sub REAPER when it can
>> safely do this (which may be quite some time later).
>>
>> > Or are you suggesting that an explicit wait on each of the child
>> > processes would somehow be safer...
>>
>> Avoiding signal handles was indeed "somehow safer" before 5.8.0,
>> because signal handlers were fundamentally unsafe (and arguably broken)
>> in perl.
>
> Hm, I thought I recalled that, even with
> Perl's broken pre-5.8 signal handling, the
> issue was most likely to surface with op's
> not on POSIX's safe list.
One function not on POSIX's safe list is malloc. And since just about
anything in perl is dynamically allocated ...
> Something like 'waitpid', which is on POSIX's safe list, in a simple
> loop was unlikely to cause a problem.
waitpid probably wasn't a problem. The loop might have been. Simply
calling the reaper function (which needs to allocate a call frame) might
have been. In the program I mentioned, a reaper function deleted an
entry from a hash - this definitely was a problem.
>> > You're right, a asynchronous wait would need to
>> > save child pids and loop until they're reaped.
>>
>> Yes. But why would you want to do that if it can be done a lot simpler
>> and more straightforward?
>>
>
> Yes I agree that's probably true here but, as you mention, you'd have
> to check for -1 because the process was reaped, stopped, or terminated
> by some signal for instance. And, if you're concerned about zombies,
> you really need to keep a list of pids to wait on.
Zombies are not a concern in this case. When you post a followup to a
question of an obvious perl beginner, please try to provide a solution
to his problem. A solution to a completely different problem will just
confuse him, especially, if you don't say that it is a solution for a
completely different problem.
> To me the solutions are very close modulo the signal function setup.
The signal function setup is the difference, yes. For the OP's problem a
signal handler is not only not needed, but does nothing at all to solve
the problem.
hp
------------------------------
Date: Fri, 18 Jan 2008 14:19:02 -0800 (PST)
From: "comp.llang.perl.moderated" <ced@blv-sam-01.ca.boeing.com>
Subject: Re: Wait for background processes to complete
Message-Id: <6c1ecc15-b3ab-4617-8494-e6a104b0633e@d21g2000prf.googlegroups.com>
On Jan 18, 1:33 pm, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
> On 2008-01-18 17:30, comp.llang.perl.moderated <c...@blv-sam-01.ca.boeing.com> wrote:
>
>
>
> > On Jan 18, 7:11 am, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
> >> On 2008-01-18 01:34, comp.llang.perl.moderated <c...@blv-sam-01.ca.boeing.com> wrote:
>
> >> > On Jan 17, 3:12 pm, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
> >> >> On 2008-01-17 00:52, comp.llang.perl.moderated <c...@blv-sam-01.ca.boeing.com> wrote:
>
> >> >> > The safest action is an asynchronous wait with a
>
> >> >> Before 5.8.0 that was actually unsafe. But while it is now safe in
> >> >> perl
>
> >> > Huh.. just for clarity, here's what I wrote:
>
> >> > use POSIX ":sys_wait_h";
> >> > $SIG{CHLD} = \&REAPER;
> >> > # now do something that forks...
> >> > ...
> >> > sub REAPER { 1 while waitpid(-1, WNOHANG)) > 0; }
>
> >> > In fact, historically, there's a clear recommendation to tight-loop
> >> > exactly as shown because you may lose signals occurring in
> >> > near concurrency if you don't.
>
> >> The problem with this approach is that until 5.8.0 (when "safe signals"
> >> were introduced), the REAPER function would be called as soon as the
> >> signal arrived regardless of what the perl interpreter was doing at the
> >> time - there was a very real risk that this would crash the perl
> >> interpreter (in a real world application which forked about 50,000 to
> >> 100,000 times a day, the parent process would crash every few days with
> >> perl 5.6.0). In C the POSIX standard explicitely states which functions
> >> are safe inside a signal handler (and the rest has to be considered
> >> unsafe), but for perl no such list existed (so everything has to be
> >> considered unsafe). In perl 5.8.0, the "real" signal handler only notes
> >> that a signal arrived, and perl will than invoke sub REAPER when it can
> >> safely do this (which may be quite some time later).
>
> >> > Or are you suggesting that an explicit wait on each of the child
> >> > processes would somehow be safer...
>
> >> Avoiding signal handles was indeed "somehow safer" before 5.8.0,
> >> because signal handlers were fundamentally unsafe (and arguably broken)
> >> in perl.
>
> > Hm, I thought I recalled that, even with
> > Perl's broken pre-5.8 signal handling, the
> > issue was most likely to surface with op's
> > not on POSIX's safe list.
>
> One function not on POSIX's safe list is malloc. And since just about
> anything in perl is dynamically allocated ...
>
> > Something like 'waitpid', which is on POSIX's safe list, in a simple
> > loop was unlikely to cause a problem.
>
> waitpid probably wasn't a problem. The loop might have been. Simply
> calling the reaper function (which needs to allocate a call frame) might
> have been. In the program I mentioned, a reaper function deleted an
> entry from a hash - this definitely was a problem.
>
> >> > You're right, a asynchronous wait would need to
> >> > save child pids and loop until they're reaped.
>
> >> Yes. But why would you want to do that if it can be done a lot simpler
> >> and more straightforward?
>
> > Yes I agree that's probably true here but, as you mention, you'd have
> > to check for -1 because the process was reaped, stopped, or terminated
> > by some signal for instance. And, if you're concerned about zombies,
> > you really need to keep a list of pids to wait on.
>
> Zombies are not a concern in this case. When you post a followup to a
> question of an obvious perl beginner, please try to provide a solution
> to his problem. A solution to a completely different problem will just
> confuse him, especially, if you don't say that it is a solution for a
> completely different problem.
I believe the OP was given a couple of solutions.
Sometimes discussions do segue off in different
directions but the info can be useful at times.
It was to me. And I disagree -- for at least
one of the solutions -- zombies could occur
and need to be dealt with.
>
> > To me the solutions are very close modulo the signal function setup.
>
> The signal function setup is the difference, yes. For the OP's problem a
> signal handler is not only not needed, but does nothing at all to solve
> the problem.
>
Again I disagree. A viable alternative solution could make use of a
SIGCHLD handler. But I think
the thread has now outlived its usefulness.
--
Charles DeRykus
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc. For subscription or unsubscription requests, send
#the single line:
#
# subscribe perl-users
#or:
# unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.
NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 1213
***************************************