You are viewing a plain text version of this content. The canonical link for it is here.
Posted to embperl@perl.apache.org by "Steven D. Arnold" <st...@neosynapse.net> on 2001/04/07 22:35:16 UTC

apparent bug in udat handling

We have been extensively using udat with great success in our software here.  However, we have discovered what seems like a bug in the way udat handles persistence.

To summarize the bug, we believe that udat does not properly store state information unless a scalar is stored as a value for a top-level key in udat.  We are using perl 5.6, Embperl 1.3b3, mod_perl 1.24 and Apache::Session 1.03.  We are using FileStore for persistence.  Documentation so that you may reproduce the bug is given below.

This message contains two embperl files and a function which is contained in the utility.pm module.  The function, set_app_state, is used to allow authors of different applications to stay entirely under a single key in udat; this allows each application author to avoid polluting udat's top-level namespace.

persist1.shtml:
---------------
[-
	use utility;

	$foo = set_app_state('foo', \%udat);
	$bar = set_app_state('bar', $foo);
-]

<HTML><HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<H1>Now on page 1</H1>
join(", ", keys(%{$bar})) = [+ join(", ", keys(%{$bar})) +]<BR>
<FORM METHOD="post" ACTION="/embperl/tests/persist2.shtml">
<INPUT TYPE="submit" VALUE="Page 2">
</FORM>
</BODY>
</HTML>


If you load the above page, $bar should be equivalent to $udat{'foo'}->{'bar'}.  This value will have no keys, so the "join" expression will show an empty result.


persist2.shtml:
---------------
[-
	use utility;

	$state = set_app_state('foo', \%udat);
	$bar   = set_app_state('bar', $state);
	$bar->{'foo'} = "whee";
	$udat{'foo'}->{'bar'}{'foo'} = "whee";
	#$udat{'bar'} = "lalala";
-]

<HTML><HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<H1>Now on page 2</H1>
	join(", ", keys(%{$bar})) = [+ join(", ", keys(%{$bar})) +]<BR>
	$udat{'foo'}->{'bar'}{'foo'} = [+ $udat{'foo'}->{'bar'}{'foo'} +]<BR>
	$udat{'bar'} = [+ $udat{'bar'} +]<BR>
<FORM METHOD="post" ACTION="/embperl/tests/persist1.shtml">
<INPUT TYPE="submit" VALUE="Page 1">
</FORM>
</BODY>
</HTML>


In the above code, $state is the same as $udat{'foo'} and $bar is the same as $udat{'foo'}->{'bar'}.  So when we say $bar->{'foo'} = "whee", that is equivalent to saying $udat{'foo'}->{'bar'}{'foo'} = "whee".

The problem is that if we click the button to take us back to page 1, the key ("foo") for $udat{'foo'}->{'bar'} is not displayed.  In other words, %udat is not storing the data structure we're creating.  However, if we uncomment the $udat{'bar'} = "lalala" line above, everything works as expected.  Said another way, if we assign a scalar to a key at the top level of udat, the remainder of our data structures are saved/remembered, but if we don't have any scalars associated with top-level keys, it doesn't work.

The set_app_state function is given below:


set_app_state from utility.pm:
------------------------------
sub set_app_state {
    my($app, $udat_ref) = @_;


    confess "function must be passed the name of the application"
        unless ($app);
    confess "function must be passed a reference to udat"
        unless (ref($udat_ref) eq "HASH");
    if (!defined($udat_ref->{$app})) {
        $udat_ref->{$app} = {};
    }
    return $udat_ref->{$app};
}


We have worked around this problem by simply assigning a value to a top-level key in the set_app_state function, so this does not represent a current problem for us.  However, it took a couple hours of debugging to isolate the problem, so IMHO this is still worth documenting/fixing.


steve




---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


RE: apparent bug in udat handling

Posted by Gerald Richter <ri...@ecos.de>.
>
> We have been extensively using udat with great success in our software
> here. However, we have discovered what seems like a bug in the way udat
> handles persistence. To summarize the bug, we believe that udat does not
> properly store state information unless a scalar is stored as a
> value for a
> top-level key in udat.

That's not a bug, but the well defined behaviour of Apache::Session. There
is no way for Apache::Session to see that a non top level key has changed.
To workaround this problem, simply do a $udat{xxx}++ in each page that
updates only non top level keys.

Gerald