[comp.lang.perl] Nasty bug ... somewhere in DBM

clewis@eci386.uucp (Chris Lewis) (03/20/90)

I've encountered what I think is a relatively drastic bug, worse,
it may be hellish to find/reproduce.  Then again, we know how good
Larry is at this.....

Perl 3, PL8 & PL12, 386/ix 1.0.6, "old" dbm configured.

As part of some relatively humongous perl code, I save things in
a content-addressible array, along the lines of:

	$sardb{'file-sz', $date} = <some number>;

[Hint, this is a sar report analyser....  $date looks like "nn:nn:nn".]

I skip through the dates that are valid, and do something like:
    if ($sardb{'file-sz', $date}) {	# have data from sar's "file" table
	local($files, $filesz, $fileov,
	      ....) = ($sardb{'file-sz', $date},
		       $sardb{'file-max', $date},
		       $sardb{'file-ov', $date},
		       ....
		      );
	use the variables fetched for analysis

There's about 12 entries in both the local(...) and ($sardb...) arrays.
In perl3 (PL 8 and 12) *some* entries are coming back as null, worse,
*some* entries are coming back with the wrong value.  The "wrong value" is,
however, a valid value for another entry.  Eg: I install

    $sardb{'file-sz', ...} = 100;
    $sardb{'file-max', ...} = 300;
    $sardb{'file-ov', ...} = 0;

and get back something like:

    $files = 100;
    $filesz = 100;
    $fileov = '';

This occurs *only* when the sardb array is associated with a DBM file via
dbmopen(...).  If I comment out the dbmopen line it works perfectly.
When I convert the big array assignment to individual ones, ala:

    $files = $sardb{'file-sz', ...};
    $filesz = $sardb{'file-max', ...};
    $fileov = $sardb{'file-ov', ...};

It will work perfectly *with* DBM.  Interestingly enough, it seems to be 
reasonably data-dependent, in that if the number of dates in the DBM
is is 2 or 140, the fetches blow the same way on the same dates.

Further, when I write a DBM traversal stand-alone in C or perl, the data
comes back just fine.

If it matters any, in the cases that I'm dealing with, the *last* sardb
reference in the array assignment hasn't been assigned to (but my program 
is guarding against that anyways).

Something to do with an interaction between the DBM caching mechanism and
array assignment temporaries perhaps?

The code is too big to reproduce.  Larry if you have problems finding this
I can try narrowing it down to a simpler program, but it will take a while.
I was hoping that this would be enough for you to find it.

I will be upgrading to PL15 shortly and testing again.
-- 
Chris Lewis, Elegant Communications Inc, {uunet!attcan,utzoo}!lsuc!eci386!clewis
Ferret mailing list: eci386!ferret-list, psroff mailing list: eci386!psroff-list

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/20/90)

In article <1990Mar19.183022.5325@eci386.uucp> clewis@eci386 (Chris Lewis) writes:
: Something to do with an interaction between the DBM caching mechanism and
: array assignment temporaries perhaps?

Precisely.  An rvalue passes references up the call tree via the stack, and
everything assumes that the reference won't be destroyed until the value is
copied to somewhere "safe".  The DBM cache code assumed it could just pass
a reference to a cache entry.  This is obviously bogus, since a reference
to multiple DBM entries can cause one entry to flush the another's cache
entry.  I'll fix it, as soon as I figure out if there's some way to avoid
copying the data every single time, which would be a performance hit.

What might be harder to fix would be assignment to a list of DBM lvalues.
I'm not sure how to fix that yet.  Meanwhile, don't do that...

Larry