test that CLONE time isn't detected as global destruction
Graham Knop [Wed, 6 Feb 2013 21:55:17 +0000 (16:55 -0500)]
t/05_thread_clone.t [new file with mode: 0644]

diff --git a/t/05_thread_clone.t b/t/05_thread_clone.t
new file mode 100644 (file)
index 0000000..4596221
--- /dev/null
@@ -0,0 +1,85 @@
+use strict;
+use warnings;
+
+use Config;
+BEGIN {
+  unless ($Config{useithreads}) {
+    print "1..0 # SKIP your perl does not support ithreads\n";
+    exit 0;
+  }
+}
+
+BEGIN {
+  unless (eval { require threads }) {
+    print "1..0 # SKIP threads.pm not installed\n";
+    exit 0;
+  }
+}
+
+BEGIN {
+  if ($ENV{DEVEL_GLOBALDESTRUCTION_PP_TEST}) {
+    no strict 'refs';
+    no warnings 'redefine';
+
+    for my $f (qw(DynaLoader::bootstrap XSLoader::load)) {
+      my ($mod) = $f =~ /^ (.+) \:\: [^:]+ $/x;
+      eval "require $mod" or die $@;
+
+      my $orig = \&$f;
+      *$f = sub {
+        die 'no XS' if ($_[0]||'') eq 'Devel::GlobalDestruction';
+        goto $orig;
+      };
+    }
+  }
+}
+
+BEGIN {
+  package Test::Scope::Guard;
+  sub new { my ($class, $code) = @_; bless [$code], $class; }
+  sub DESTROY { my $self = shift; $self->[0]->() }
+}
+BEGIN {
+  package Test::Thread::Clone;
+  my @code;
+  sub new { my ($class, $code) = @_; push @code, $code; bless [$code], $class; }
+  sub CLONE { $_->() for @code }
+}
+
+use threads;
+use threads::shared;
+
+print "1..3\n";
+
+our $had_error :shared;
+END { $? = $had_error||0 }
+
+sub ok ($$) {
+  $had_error++, print "not " if !$_[0];
+  print "ok";
+  print " - $_[1]" if defined $_[1];
+  print "\n";
+}
+
+# load it before spawning a thread, that's the whole point
+use Devel::GlobalDestruction;
+
+our $cloner = Test::Thread::Clone->new(sub {
+    ok( ! in_global_destruction(), "CLONE is not GD" );
+});
+our $global = Test::Scope::Guard->new(sub {
+    ok( in_global_destruction(), "Final cleanup object destruction properly in GD in " . (threads->tid ? 'thread' : 'main program') );
+});
+
+sub do_test {
+  # just die so we don't need to deal with testcount skew
+  unless ( ($_[0]||'') eq 'arg' ) {
+    $had_error++;
+    die "Argument passing failed!";
+  }
+  # nothing really to do in here
+  1;
+}
+
+threads->create('do_test', 'arg')->join
+  or $had_error++;