Subject: | adExport to XML hangs while flock($fh, LOCK_EX) |
I experienced this while attempting to adExport from an in-memory ARRAY
table to an XML file.
Calling adExport($arraytable, "XML", $filename) hangs indefinitely.
Running my program through a debugger I noticed that Perl is waiting for
flock($fh, LOCK_EX), which happens in
AnyData::Storage::File::open_local_file, line 104. The complete stack
trace at this point looks like this:
$ =
AnyData::Storage::File::open_local_file(ref(AnyData::Storage::PassThru),
'/home/zmousm/rstab.xml', 'o') called from file
`/usr/lib/perl5/site_perl/5.8.5/AnyData/Format/XML.pm' line 876
@ = AnyData::Format::XML::export(ref(AnyData::Format::XML),
ref(AnyData::Storage::PassThru), '/home/zmousm/rstab.xml') called from
file `/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 100
@ = AnyData::export(ref(AnyData), '/home/zmousm/rstab.xml') called from
file `/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 664
@ = AnyData::adConvert('adHash', ref(AnyData), 'XML',
'/home/zmousm/rstab.xml', undef, undef) called from file
`/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 608
@ = AnyData::adExport(ref(HASH), 'XML', '/home/zmousm/rstab.xml') called
from file `/home/zmousm/rgrWalk.pl' line 271
While stepping through the calling stack, I realized this happens
because Perl has already opened this file and obtained an exclusive lock
on $fh. This happens because:
my $target_ad = adTable(
$target_format,$target_file_name,'o',undef,$target_flags
);
is called, in AnyData::adConvert, line 649. Once again, the stack trace
at the time this (first) lock is obtained looks like this:
$ =
AnyData::Storage::File::open_local_file(ref(AnyData::Storage::PassThru),
'/home/zmousm/rstab.xml', 'o') called from file
`/usr/lib/perl5/site_perl/5.8.5/AnyData/Format/XML.pm' line 876
@ = AnyData::Format::XML::export(ref(AnyData::Format::XML),
ref(AnyData::Storage::PassThru), '/home/zmousm/rstab.xml') called from
file `/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 100
@ = AnyData::export(ref(AnyData), '/home/zmousm/rstab.xml') called from
file `/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 664
@ = AnyData::adConvert('adHash', ref(AnyData), 'XML',
'/home/zmousm/rstab.xml', undef, undef) called from file
`/usr/lib/perl5/site_perl/5.8.5/AnyData.pm' line 608
@ = AnyData::adExport(ref(HASH), 'XML', '/home/zmousm/rstab.xml') called
from file `/home/zmousm/rgrWalk.pl' line 271
A few lines after the previous call to adTable, AnyData::export is
called, which subsequently calls AnyData::Format::XML::export, but this
last function ignores the already open file handle, available at
$storage->{fh}, overwriting $fh by reopening the file at line 876, as
shown in the first trace.
In order to fix this, I believe there are a couple of possibilities:
1) The adTable call should restrict itself to a shared lock, opening the
file read-only, since it seems it only wants to prepare $target_ad and
it is not going to write to the file yet.
2) The file handle should be closed before opening the file again, at
some time between the two calls to adTable and export.
3) AnyData::Format::XML::export should check if the file is already open
before attempting to open it again.
I'm sorry for not providing a patch, but my knowledge of Perl and
specifically my familiarity with the complex data structures in AnyData
code is far too limited, in other words I am totally lost wrt the
implications applying any of the above fixes may have.
I hope this (first) bug report makes sense ;)