develooper Front page | perl.perl5.porters | Postings from March 2000

Unpublished Perl Secrets #89: $@->PROPAGATE

From:
Tom Christiansen
Date:
March 22, 2000 07:38
Subject:
Unpublished Perl Secrets #89: $@->PROPAGATE
Message ID:
4245.953739476@chthon
Here's what I've learned about the mysterious and undocumentd
PROPAGATE.  Have any of you used it?   I strongly wonder whether
some of these aren't implementational accidents.

0.  If you die with a reference which is unblessed, Perl prints 
    just the stringified reference, but not a newline or anything 
    else.

	% perl -e 'die []'
	ARRAY(0xf6150)% 

    That seems a bug.  This can get kind of weird though, if the
    thing has a stringify method of its own.

	% perl -MMath::BigInt=:constant -e '$x = 1; die $x'
	+1% 

	% perl -MMath::Complex -e '$x = i * i * i; die $x'
	[1,-pi/2]% 

    I think that's right.  Well, probably.

1.  The object's PROPAGATE method is called with two arguments:
    the current line and file.  This should be documented.

2.  Once this method call has completed, whatever was left lying
    about on the stack--which is guaranteed to be something - is
    stuffed back into $@, overwriting whatever was there before.
    This means you can exchange one kind of exception for another,
    but in a highly controlled fashion, just with a simple return
    statement.  This should be documented.

3.  Because the method is called with flags G_SCALAR|G_EVAL|G_KEEPERR,
    if you trigger another exception from within the PROPAGATE hook,
    that hook exits immediately, but is squelched.  However, as
    with any exceptionally exited block, that leaves undef on your
    stack. Therefore, by observation #2, that's what lands in $@.
    Now that $@ is empty, it appears to you as though no exception
    occurred.  This appears to be a bug.

4.  If you *intentionally* die "oops" within PROPAGATE, your new
    argument is doesn't show up in $@.  You must assign, not die.
    If you die, you will place undef in $@, and the new message is
    lost completely.  This appears to be a bug, or at least, an
    unfriendly feature.

5.  And if you should have the audacity to die with another exception
    object (not directly, but stuff into $@ and then no-arg die'd)
    from within your hook, you're probably in trouble.  Either 

        (a) it resolves to the same method as you're in now, in
        which case you dive recursively into that hook until you
        SEGV out of your stack.  This is probably UBD (what we
	closed out bug reports as: user brain damage), but still...

        Or (b) it's a different class, but that other class cannot
        use the return trick to create a new exception.  You're
        still in a second-level die, and so your return is wiped
        out as though you'd returned undef -- and thus, had had no
        exception at all.   This appears to be a bug.

        There's also (c) where you end up with indirect recursion
        as two error classes raise each other; this is also stack
        death, of course.  This is either like a or b or both.
	The problem is that you could easily end up with a daisy
	chain of these all strung together indirectly, and you could
	never know it.

6.  You can, however, usefully but manually call $@->SUPER::PROPAGATE
    if you ->can, and if you return its return value, this appears to
    be fine.  I'm not sure whether to document this, as it in some sense
    falls out of #2.


--tom



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