Problem with call to system(), I think.

Discussion in 'Perl Misc' started by Ted Byers, Dec 2, 2008.

  1. Ted Byers

    Ted Byers Guest

    Here is the simple loop with the problem:

    print "\n\nProcessing merchant data: \n";
    foreach $merchant(sort keys %merchants) {
    print "\tmerchant name: $merchant\n\tmid: $merchants{$merchant}\n
    \tAPI user name: $merchants_usernames{$merchant}\n\n";
    system("activity.report.1.pl \"$merchant\" $merchants_usernames
    {$merchant} $merchants{$merchant} $date_string 1>$dir\\activity.Report.
    $merchant.stdout 2>$dir\\activity.Report.$merchant.stderr") == 0
    or warn "Problem creating activity report for $merchant\n";
    }

    I am using "use strict" and $| = 1, from the top of the script.

    The hash is fully populated and there are no null values in any
    variable in the code shown.

    The problem is that for 90% of the merchants, the script
    activity.report.1.pl executes fine, producing the expected files
    (those with the contents of stdout and stderr, as well as the desired
    PDF file). For the rest, we get the merchant name, and the values
    from the two hashes (that contain values to be provided as arguments
    for the activity report script), followed by:

    The process cannot access the file because it is being used by another
    process.
    Problem creating activity report for xxxxxxxxxxx xxxxxxx

    The second line shown here is obviously from the die clause, but where
    is the message "The process cannot access the file because it is being
    used by another process." coming from? None of the information that
    is written to stdout by the activity report script appears (e.g. the
    first statement is to write to standard out the values of the
    arguments), and nothing appears to be written to stderr either. The
    files that ought to contain what is supposed to be written to stdout
    and stderr don't even get created, hence my guess that the problem is
    with the call to system.

    Having previously printed out the contents of the hashes, I know the
    correct arguments are being passed to "activity.report.1.pl" (from
    comparing what was printed to the contents of the database table from
    which the values are obtained, and what the activity report script
    prints to standard out for the arguments it has received), and
    activity.report.1.pl always runs to completion successfully when I
    invoke it manually with all the same arguments that this script uses,
    so I am at a loss. Why is my call to system failing (or how can I
    find out), and what can be done to fix it? And why would it fail for
    only 10% of the merchants?

    Thanks

    Ted
    Ted Byers, Dec 2, 2008
    #1
    1. Advertising

  2. Ted Byers

    Guest

    Ted Byers <> wrote:

    > system("activity.report.1.pl \"$merchant\" $merchants_usernames
    > {$merchant} $merchants{$merchant} $date_string 1>$dir\\activity.Report.
    > $merchant.stdout 2>$dir\\activity.Report.$merchant.stderr") == 0


    Line wrapping really makes that code hard to read. But it could suck a
    little less if you used the qq{} construct in place of the "", so that
    literal double-quotes did not need to be escaped.

    > or warn "Problem creating activity report for $merchant\n";


    You should probably include $? and $! in the warning. It might help
    and can't hurt.

    ....

    > The problem is that for 90% of the merchants, the script
    > activity.report.1.pl executes fine, producing the expected files
    > (those with the contents of stdout and stderr, as well as the desired
    > PDF file). For the rest, we get the merchant name, and the values
    > from the two hashes (that contain values to be provided as arguments
    > for the activity report script), followed by:
    >
    > The process cannot access the file because it is being used by another
    > process.
    > Problem creating activity report for xxxxxxxxxxx xxxxxxx
    >
    > The second line shown here is obviously from the die clause,


    warn clause, not die clause

    > but where
    > is the message "The process cannot access the file because it is being
    > used by another process." coming from?


    I think it is coming from the shell-like-thingy that Perl spawns to run the
    command.

    It is a locking issue. I can reproduce the behavior on Windows simply by
    opening the target activity.report.1.pl in Excel (which locks it).

    I can solve the problem by invoking Perl explicitly in the system command,
    rather than implicitly via the extension of the target:

    system(qq{perl activity.report.1.pl blah blah blah}) ==0 or warn ...;

    rather than:

    system(qq{activity.report.1.pl blah blah blah}) ==0 or warn ...;

    Although if something has your script locked while you are trying to run
    it, maybe failure is the right thing to happen.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Dec 2, 2008
    #2
    1. Advertising

  3. Ted Byers

    Guest

    On Tue, 2 Dec 2008 08:34:31 -0800 (PST), Ted Byers <> wrote:

    >Here is the simple loop with the problem:
    >
    >print "\n\nProcessing merchant data: \n";
    >foreach $merchant(sort keys %merchants) {
    > print "\tmerchant name: $merchant\n\tmid: $merchants{$merchant}\n
    >\tAPI user name: $merchants_usernames{$merchant}\n\n";
    > system("activity.report.1.pl \"$merchant\" $merchants_usernames
    >{$merchant} $merchants{$merchant} $date_string 1>$dir\\activity.Report.
    >$merchant.stdout 2>$dir\\activity.Report.$merchant.stderr") == 0
    > or warn "Problem creating activity report for $merchant\n";
    >}
    >
    >I am using "use strict" and $| = 1, from the top of the script.
    >
    >The hash is fully populated and there are no null values in any
    >variable in the code shown.
    >
    >The problem is that for 90% of the merchants, the script
    >activity.report.1.pl executes fine, producing the expected files
    >(those with the contents of stdout and stderr, as well as the desired
    >PDF file). For the rest, we get the merchant name, and the values
    >from the two hashes (that contain values to be provided as arguments
    >for the activity report script), followed by:
    >
    >The process cannot access the file because it is being used by another
    >process.
    >Problem creating activity report for xxxxxxxxxxx xxxxxxx
    >

    [snip]

    The docs say if shell metachars on a single scalar argument it
    will pass the entire string unalterred to the shell command processor.
    Otherwise it will split the arguments into words and pass to execvp().

    In that case it couldn't hurt to try to create your own controlled
    argument list. Try it with and without double quotes.

    @args = (
    "activity.report.1.pl",
    "\"$merchant\"",
    $merchants_usernames{$merchant},
    $merchants{$merchant},
    $date_string,
    "1>$dir\\activity.Report.$merchant.stdout",
    "2>$dir\\activity.Report.$merchant.stderr",
    );

    @args = (
    "activity.report.1.pl",
    "\"$merchant\"",
    "\"$merchants_usernames{$merchant}\"",
    "\"$merchants{$merchant}\"",
    "\"$date_string\"",
    "\"1>$dir\\activity.Report.$merchant.stdout\"",
    "\"2>$dir\\activity.Report.$merchant.stderr\"",
    );

    system(@args) == 0 or die "system @args failed: $?"


    sln
    , Dec 2, 2008
    #3
  4. On Tue, 02 Dec 2008 17:47:31 +0000, sln wrote:
    > @args = (
    > "activity.report.1.pl",
    > "\"$merchant\"",
    > $merchants_usernames{$merchant},
    > $merchants{$merchant},
    > $date_string,
    > "1>$dir\\activity.Report.$merchant.stdout",
    > "2>$dir\\activity.Report.$merchant.stderr",
    > );
    >


    Those last few arguments wouldn't work well. It's probably best to use
    something like IPC:Open3 here.

    Regards,

    Leon Timmermans
    Leon Timmermans, Dec 3, 2008
    #4
  5. Ted Byers

    Ted Zlatanov Guest

    On 03 Dec 2008 22:53:28 GMT Leon Timmermans <> wrote:

    LT> On Tue, 02 Dec 2008 17:47:31 +0000, sln wrote:
    >> @args = (
    >> "activity.report.1.pl",
    >> "\"$merchant\"",
    >> $merchants_usernames{$merchant},
    >> $merchants{$merchant},
    >> $date_string,
    >> "1>$dir\\activity.Report.$merchant.stdout",
    >> "2>$dir\\activity.Report.$merchant.stderr",
    >> );
    >>


    LT> Those last few arguments wouldn't work well. It's probably best to use
    LT> something like IPC:Open3 here.

    IPC::Run is also good, although the docs are a bit confusing.

    Ted
    Ted Zlatanov, Dec 4, 2008
    #5
  6. Ted Byers

    Guest

    On Thu, 04 Dec 2008 10:42:41 -0600, Ted Zlatanov <> wrote:

    >On 03 Dec 2008 22:53:28 GMT Leon Timmermans <> wrote:
    >
    >LT> On Tue, 02 Dec 2008 17:47:31 +0000, sln wrote:
    >>> @args = (
    >>> "activity.report.1.pl",
    >>> "\"$merchant\"",
    >>> $merchants_usernames{$merchant},
    >>> $merchants{$merchant},
    >>> $date_string,
    >>> "1>$dir\\activity.Report.$merchant.stdout",
    >>> "2>$dir\\activity.Report.$merchant.stderr",
    >>> );
    >>>

    >
    >LT> Those last few arguments wouldn't work well. It's probably best to use
    >LT> something like IPC:Open3 here.
    >
    >IPC::Run is also good, although the docs are a bit confusing.
    >
    >Ted


    I posted an arglist with each one quoted. That is the correct fix with one
    small change. I didn't see the redirect parameters.

    Below does both show the real problem(s) in 'Consideration #1 and #2' and
    the fix in 'Consideration #3 and #4'.

    There is only one problem when the OP gets 'used by another process' message.
    No need to do IPC:Open3 unless this doesen't work. But I've got money say's this
    is the actual fix for his/her problem.

    Unfortunately, he/she has opened another thread on this with a different angle
    trying to fix the same problem, and he/she will never read this.

    Good luck!


    sln

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

    Command line:
    ____________________________
    c:\temp>perl ttt.pl

    Consideration #1:
    ---------------------------
    The process cannot access the file because it is being used by another process.
    problem with jjj.pl: 256

    Consideration #2:
    ---------------------------

    Consideration #3:
    ---------------------------
    Consideration #4:
    ---------------------------

    c:\temp>

    ____________________________________________________________

    ttt.pl:
    -----------------------------------------
    use strict;
    use warnings;

    my @args;
    my $dir = "c:\\temp";
    my $merchant = "Home Depot";

    my %merchants = ($merchant => 'home depot');
    my %merchants_usernames = ($merchant => 'H DEPOT');
    my $date_string = "Jan 1, 2009";

    print "Consideration #1:\n---------------------------\n";
    system("perl jjj.pl \"$merchant\" $merchants_usernames{$merchant} $merchants{$merchant} $date_string 1>$dir\\activity.Report.$merchant.stdout1 2>$dir\\activity.Report.$merchant.stderr1") == 0
    or warn "problem with jjj.pl: $?\n";

    print "\nConsideration #2:\n---------------------------\n";
    @args = (
    'jjj.pl',
    "\"$merchant\"",
    $merchants_usernames{$merchant},
    $merchants{$merchant},
    $date_string,
    "1>\"$dir\\activity.Report.$merchant.stdout2\"",
    "2>\"$dir\\activity.Report.$merchant.stderr2\"",
    );
    system("perl @args") == 0 or warn "problem with jjj.pl: $?";

    print "\nConsideration #3:\n---------------------------\n";
    @args = (
    'jjj.pl',
    "\"$merchant\"",
    "\"$merchants_usernames{$merchant}\"",
    "\"$merchants{$merchant}\"",
    "\"$date_string\"",
    "1>\"$dir\\activity.Report.$merchant.stdout3\"",
    "2>\"$dir\\activity.Report.$merchant.stderr3\"",
    );
    system("perl @args") == 0 or warn "problem with jjj.pl: $?";


    print "Consideration #4:\n---------------------------\n";
    system("perl jjj.pl \"$merchant\" \"$merchants_usernames{$merchant}\" \"$merchants{$merchant}\" \"$date_string\" 1>\"$dir\\activity.Report.$merchant.stdout4\"
    2>\"$dir\\activity.Report.$merchant.stderr4\"") == 0
    or warn "problem with jjj.pl: $?\n";




    jjj.pl:
    -----------------------------------------
    use strict;
    use warnings;

    for (@ARGV) {
    print "$_\n";
    }


    activity.Report.Home:
    -------------------------------------


    activity.Report.Home Depot.stdout2:
    --------------------------------------
    Home Depot
    H
    DEPOT
    home
    depot
    Jan
    1,
    2009


    activity.Report.Home Depot.stdout3:
    activity.Report.Home Depot.stdout4:
    ---------------------------------------
    Home Depot
    H DEPOT
    home depot
    Jan 1, 2009
    , Dec 4, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    597
  2. Replies:
    1
    Views:
    864
    Jack Klein
    Apr 13, 2005
  3. system call and library call

    , Aug 22, 2005, in forum: C Programming
    Replies:
    7
    Views:
    3,009
    Jonathan Bartlett
    Aug 23, 2005
  4. ejn14ls6
    Replies:
    0
    Views:
    330
    ejn14ls6
    Dec 18, 2007
  5. David Mark
    Replies:
    17
    Views:
    234
    David Mark
    Mar 23, 2010
Loading...

Share This Page