Try harder to detect tie(%^H) clashes
Peter Rabbitson [Wed, 3 Aug 2011 20:19:27 +0000 (22:19 +0200)]
lib/namespace/clean.pm

index ae147cc..ab08964 100644 (file)
@@ -12,9 +12,13 @@ our $VERSION = '0.20_01';
 $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE';
 
 BEGIN {
+
+  # when changing also change in Makefile.PL
+  my $b_h_eos_req = '0.07';
+
   if (eval {
     require B::Hooks::EndOfScope;
-    B::Hooks::EndOfScope->VERSION('0.07');  # when changing also change in Makefile.PL
+    B::Hooks::EndOfScope->VERSION($b_h_eos_req);
     1
   } ) {
     B::Hooks::EndOfScope->import('on_scope_end');
@@ -22,6 +26,14 @@ BEGIN {
   else {
     eval <<'PP' or die $@;
 
+  use Tie::Hash ();
+
+  {
+    package namespace::clean::_TieHintHash;
+
+    use base 'Tie::ExtraHash';
+  }
+
   {
     package namespace::clean::_ScopeGuard;
 
@@ -30,16 +42,36 @@ BEGIN {
     sub DESTROY { $_[0]->[0]->() }
   }
 
-  use Tie::Hash ();
 
   sub on_scope_end (&) {
     $^H |= 0x020000;
 
     if( my $stack = tied( %^H ) ) {
+      if ( (my $c = ref $stack) ne 'namespace::clean::_TieHintHash') {
+        die <<EOE;
+========================================================================
+               !!!   F A T A L   E R R O R   !!!
+
+                 foreign tie() of %^H detected
+========================================================================
+
+namespace::clean is currently operating in pure-perl fallback mode, because
+your system is lacking the necessary dependency B::Hooks::EndOfScope $b_h_eos_req.
+In this mode namespace::clean expects to be able to tie() the hinthash %^H,
+however it is apparently already tied by means unknown to the tie-class
+$c
+
+Since this is a no-win situation execution will abort here and now. Please
+try to find out which other module is relying on hinthash tie() ability,
+and file a bug for both the perpetrator and namespace::clean, so that the
+authors can figure out an acceptable way of moving forward.
+
+EOE
+      }
       push @$stack, namespace::clean::_ScopeGuard->arm(shift);
     }
     else {
-      tie( %^H, 'Tie::ExtraHash', namespace::clean::_ScopeGuard->arm(shift) );
+      tie( %^H, 'namespace::clean::_TieHintHash', namespace::clean::_ScopeGuard->arm(shift) );
     }
   }