develooper Front page | perl.perl5.porters | Postings from September 2014

Re: Hash::Util and read-only values

Thread Previous | Thread Next
From:
Father Chrysostomos
Date:
September 20, 2014 01:12
Subject:
Re: Hash::Util and read-only values
Message ID:
20140920011159.9799.qmail@lists-nntp.develooper.com
Yves Orton wrote:
> On 20 September 2014 00:48, Father Chrysostomos <sprout cpan.org> wrote:
> 
> > With Hash::Util::hv_store and Hash::Util::unlock_value, it is possible
> > to turn off the read-only flag of any scalar.
> >
> > There are cases where the core uses this flag to protect things that
> > must not be modified.  So we need to stop Hash::Util from being able
> > to do this.
> >                                      
> 
> This suggests a deeper design problem that I think needs to be thought
> through independently of Hash::Util.
> 
> 
> >
> > (I bring this up, because with lvalue references it will become easier
> > to do this by mistake.)
> >
> >
> Yes, exactly, that is the problem.
> 
> 
> > So we need to distinguish truly read-only values from values locked by
> > Hash::Util.
> >
> > 
> Or alternatively we need to change things that are using the read-only bit
> for different purposes.
> 
> 
> > Hash::Util::unlock_value should croak for any read-only (as opposed to
> > locked) value.
> 
> 
> There is no difference between a locked value and a read only value.

Currently there is none, but introducing such a distinction is easy.

> > But should Hash::Util::lock_value croak for those, or
> > just return?  I am inclined to think it should croak, as a successful
> > lock_value implies that later unlock_value will work.
> >
> > Actually, since locking or unlocking an entire hash's values at
> > once is possible, should (un)locking silently do nothing with read-
> > only values?
> >
> 
> For me this has subject has XY problem written all over it.

In this case the solution for Y would be identical to the solu-
tion for X.

> I think we should solve the X problem, that we use the read only flag for
> multiple purposes.

In the perl core, the read-only flag only serves one purpose aside
from Hash::Util.

> Once we solve that there will be no Y problem, that Hash::Util does the
> wrong thing.

Since Hash::Util is the part of the core (if you will) that uses the
flag differently, we do need to discuss how it will behave, since that
is where the bugs in the design show through.

> Independently, I think it is arguable that the locked hash implementation
> is broken to the point of being nearly unusable.
> 
> Specifically there is no way to lock a hash so you can not modify, delete
> or add keys or values, but can still do things like fetch a missing key,
> call exists on a missing key etc.

I am not interested in solving this at present (if ever).

> Also related to this is the question of how to serialize a locked or read
> only value?

Or this.  (DDS already does make_ro though.  Hey, do you know about
DDS?  I recommend it.)

Okay, the two meanings for SvREADONLY are:

1) This value must not be modified and must be protected at all costs.
   (Call this 'protected'.)
2) This value is temporarily read-only, at the user's request.
   (Call this 'locked'.)

Every use of SvREADONLY_on in the perl core, aside from Hash::Util, is
for meaning 1.  Hash::Util's use of it is for meaning 2.

(Before Hash::Util came along, no. 1 was the only meaning.)

So what should Hash::Util::(un)lock_value do when it encounters a pro-
tected value (assuming we have already introduced the distinction with
internal flags)?  Croak?  Silently do nothing?

Now, as for flag usage and XS macros, do we want to take into account
the various CPAN modules that do SvREADONLY_on/off (which modules have
always been buggy to some extent)?

Do we want SvREADONLY to refer to locked values or to protected
values?  The former would make such CPAN modules safer, but
SvREADONLY_off would be effectively a silent no-op for protected val-
ues.  The latter would have them continue to behave exactly as they do
(dangerously).

BTW, here is one symptom of the problem:

$ perl -MHash::Util=hv_store,unlock_value -MScalar::Util=weaken -e 'DESTROY{hv_store %h, k=>$_[0]; unlock_value %h, "k"; $x = $_[0]; weaken $_[0]; undef %h} $_ = bless[]'
panic: magic_killbackrefs (flags=ff) during global destruction.

I have managed to get variants of this to crash in the past.


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About