diff options
author | Gerard Goossen <gerard@ggoossen.net> | 2010-11-06 12:22:29 +0100 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-07-04 21:31:12 -0700 |
commit | 7b81e54987e52ee2d72541b3cbc5c62e099d3429 (patch) | |
tree | 65b90a07fb7bdb0add7a1140dc452817ba4fd677 | |
parent | 998e043925965cf6a2a62e8b7f519b4bba121b13 (diff) | |
download | perl-7b81e54987e52ee2d72541b3cbc5c62e099d3429.tar.gz |
Add a test for perl_clone with CLONEf_COPY_STACKS to XS-APItest.
CLONEf_COPY_STACKS is only used by the windows pseudo-fork.
This test allows testing/debugging of CLONEf_COPY_STACK without needing threads or Windows.
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | ext/XS-APItest/APItest.xs | 55 | ||||
-rw-r--r-- | ext/XS-APItest/t/clone-with-stack.t | 53 |
3 files changed, 109 insertions, 0 deletions
@@ -3657,6 +3657,7 @@ ext/XS-APItest/t/call_checker.t test call checker plugin API ext/XS-APItest/t/caller.t XS::APItest: tests for caller_cx ext/XS-APItest/t/call.t XS::APItest extension ext/XS-APItest/t/cleanup.t test stack behaviour on unwinding +ext/XS-APItest/t/clone-with-stack.t test clone with CLONEf_COPY_STACKS works ext/XS-APItest/t/cophh.t test COPHH API ext/XS-APItest/t/copyhints.t test hv_copy_hints_hv() API ext/XS-APItest/t/customop.t XS::APItest: tests for custom ops diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs index 21f417d25c..acd1b5e42f 100644 --- a/ext/XS-APItest/APItest.xs +++ b/ext/XS-APItest/APItest.xs @@ -2682,6 +2682,61 @@ CODE: XSRETURN_UNDEF; } +#ifdef USE_ITHREADS + +void +clone_with_stack() +CODE: +{ + PerlInterpreter *interp = aTHX; /* The original interpreter */ + PerlInterpreter *interp_dup; /* The duplicate interpreter */ + int oldscope = 1; /* We are responsible for all scopes */ + + interp_dup = perl_clone(interp, CLONEf_COPY_STACKS | CLONEf_CLONE_HOST ); + + /* destroy old perl */ + PERL_SET_CONTEXT(interp); + + POPSTACK_TO(PL_mainstack); + dounwind(-1); + LEAVE_SCOPE(0); + + while (interp->Iscopestack_ix > 1) + LEAVE; + FREETMPS; + + perl_destruct(interp); + perl_free(interp); + + /* switch to new perl */ + PERL_SET_CONTEXT(interp_dup); + + /* continue after 'clone_with_stack' */ + interp_dup->Iop = interp_dup->Iop->op_next; + + /* run with new perl */ + Perl_runops_standard(interp_dup); + + /* We may have additional unclosed scopes if fork() was called + * from within a BEGIN block. See perlfork.pod for more details. + * We cannot clean up these other scopes because they belong to a + * different interpreter, but we also cannot leave PL_scopestack_ix + * dangling because that can trigger an assertion in perl_destruct(). + */ + if (PL_scopestack_ix > oldscope) { + PL_scopestack[oldscope-1] = PL_scopestack[PL_scopestack_ix-1]; + PL_scopestack_ix = oldscope; + } + + perl_destruct(interp_dup); + perl_free(interp_dup); + + /* call the real 'exit' not PerlProc_exit */ +#undef exit + exit(0); +} + +#endif /* USE_ITHREDS */ SV* take_svref(SVREF sv) diff --git a/ext/XS-APItest/t/clone-with-stack.t b/ext/XS-APItest/t/clone-with-stack.t new file mode 100644 index 0000000000..943a123427 --- /dev/null +++ b/ext/XS-APItest/t/clone-with-stack.t @@ -0,0 +1,53 @@ +#!perl + +use strict; +use warnings; + +require "../../t/test.pl"; + +use XS::APItest; + +# clone_with_stack creates a clone of the perl interpreter including +# the stack, then destroys the original interpreter and runs the +# remaining code using the new one. +# This is like doing a psuedo-fork and exiting the parent. + +use Config; +if (not $Config{'useithreads'}) { + skip_all("clone_with_stack requires threads"); +} + +plan(3); + +fresh_perl_is( <<'----', <<'====', undef, "minimal clone_with_stack" ); +use XS::APItest; +clone_with_stack(); +print "ok\n"; +---- +ok +==== + +fresh_perl_is( <<'----', <<'====', undef, "inside a subroutine" ); +use XS::APItest; +sub f { + clone_with_stack(); +} +f(); +print "ok\n"; +---- +ok +==== + +{ + local our $TODO = "clone_with_stack inside a begin block"; + fresh_perl_is( <<'----', <<'====', undef, "inside a BEGIN block" ); +use XS::APItest; +BEGIN { + clone_with_stack(); +} +print "ok\n"; +---- +ok +==== + +} |