Problem with call to system(), I think.

T

Ted Byers

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
 
X

xhoster

Ted Byers said:
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.
 
S

sln

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
 
L

Leon Timmermans

@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
 
T

Ted Zlatanov

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
 
S

sln

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:
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top