warwick has asked for the wisdom of the Perl Monks concerning the following question:

The problem is...
system processes aren't waiting for the previous process to complete. What is the best way to fix this problem?

Thanks in advance!

Bill

if ($filename{$num}ne '') { system("/3rdparty/perl/bin/sunos5/lwp-request -p http://pr +oxy-syr.global.lmco.com $hostname$url -C $user:$password>$temp$file") +; system("chmod 777 $temp$file"); system("acroread -toPostScript $temp$file"); system("lp -d ep5_hpp01 $temp *.ps"); }

2001-10-02 Edit by Corion - Fixed formatting, added CODE tags

Replies are listed 'Best First'.
Re: Wait
by gbarr (Monk) on Oct 03, 2001 at 01:32 UTC
    I see, at least in the first call, that you are passing a URL. Do any of the variables passed in contain & ?

    system() with a single argument will call the shell which will interpret the & to mean background the process. If that happens system() will return straight away.

    The solution is to use the multi-arg system(), but in the first instance you also want to redirect, so you may have to fork() and exec()

    Something like

    my $pid = fork(); if ($pid) { wait($pid); # Plus appropriate checking } elsif(defined($pid)) { open(STDOUT,">$temp$file") or die "Cannot open $temp$file: $!\n"; exec(qw("/3rdparty/perl/bin/sunos5/lwp-request -p http://proxy-syr +.global.lmco.com),"$hostname$url","-C","$user:$password"); die "Cannot exec: $!\n"; } else { die "Cannot fork: $!\n"; } system(qw(chmod 777),"$temp$file"); system(qw(acroread -toPostScript),"$temp$file"); system(qw(lp -d ep5_hpp01), $temp, glob("*.ps"));
Re: Wait
by tachyon (Chancellor) on Oct 03, 2001 at 00:45 UTC

    system() forks a child to run the program via an exec and is supposed to wait for the child to finish. Assuming what you say is actually the problem (not the typo noted above):

    I would suspect that the redirection to $temp$file is the problem with the system call returning while the shell is doing the write producing a race condition which perl is winning. Have you tried adding a say sleep 1; after the first system call to see if this fixes the problem?

    To ensure that the first call has finished you could call it with backticks and capture the output. Then use perl to write $temp$file.

    $data = `/3rdparty/perl/bin/sunos5/lwp-request -p http://proxy-syr.glo +bal.lmco.com $hostname$url -C $user:$password`; open F, ">$temp$file" or die "Can't write $temp$file, $1\n"; print F $data; close F; # you don't need the system call to do chmod as Perl has one chmod 777, $tempfile or die "Can't chmod $temp$file $!\n"; system("acroread -toPostScript $temp$file"); system("lp -d ep5_hpp01 $temp *.ps");

    If none of that works you could resort to implementing the whole thing in pure Perl.

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      The shell doesn't do any writing here. It merely redirects STDOUT to point to the file and then fork/execs the new process. Backticks won't do anything more than system() here either -- it won't ensure you get all of the output. If the system'd process forks itself into the background, backticks (like system) will return immediately and stop grabbing output at that point.

      You need to find out which process is not waiting (lwp-request?) and either stop it from doing that or reimplement that part only in perl. (gbarr's suggestion to check for '&' is a good start.)

      bluto

Re: Wait
by C-Keen (Monk) on Oct 03, 2001 at 00:48 UTC
    A thing to do would be to fork for every system call and use exec to do your calls. In the parent thread use the wait function. I have written a brief example for this node

    Hope this helps,
    C-Keen

Re: Wait
by CubicSpline (Friar) on Oct 03, 2001 at 00:31 UTC
    That is the way that system() behaves. I do not know that this is the best way to address this problem, but if you make your calls in between backtics, the script will wait for the calls to return. You could try this:
    if ($filename{$num}ne '') { `/3rdparty/perl/bin/sunos5/lwp-request -p http://proxy-syr +.global.lmco.com $hostname$url -C $user:$password>$temp$file`; `chmod 777 $temp$file`; `acroread -toPostScript $temp$file`; `lp -d ep5_hpp01 $temp *.ps`; }
    Or you could also look into the wait function.

      Sorry, that's wrong. system waits for its child processes to complete. The big difference between it and backticks is that backticks will allow you pick up the output. Please read the top part of the relevant doc.

      Looks like he just has a typo: Shouldn't the last line be: system("lp -d ep5_hpp01 $temp/*.ps");Presuming that $temp is a directory name. Else it'll glob to any .ps files in the current directory. Otherwise I can't think of why it would appear to be running the commands in parallel.

      HTH

        My bad! Thanks for the correction VSarkiss. I normally do my perl programming on Windows using ActivePerl and I've had some funkiness with using system(). I've just taken to using backticks when it's really necessary to wait until the child is done executing.