daveola has asked for the wisdom of the Perl Monks concerning the following question:
The perl code uses 'exit' in places in order to exit the perl code, but the *perl* exit in eval_pv evidently does an 'exit' in the C program and it kills my program entirely.
How can I have embedded perl that can exit (and hence do things like flush filehandles, call END blocks, etc..) but not exit the C main program?
I found the ability to catch/redefine *CORE::GLOBAL::exit, but that just means I don't exit the perl eval anymore.
Is this possible? i.e., keep eval_pv from exiting my C program but still "exit" the perl code?
To clarify, I've edited the test program from @bliako. We are simply embedding perl code that does:
sub doubler { return $_[0] * 2 if $#_ == 0; print STDERR "doubler() Error, wrong number of args\n"; exit(-1); } print "Start perl code\n"; print "Doubler of 42: ".doubler(42)."\n"; print "Doubler of <missing arg>: ".doubler()."\n"; ## oops! called doubler(<num>) wrong! print "Done\n";The error created in the second call to doubler causes an exit.
But this exit in the perl code is causing the C code to exit, which I do not want.
I can't replace the exit with a 'return' because I want the perl code to exit, just not the C code.
I can't catch exit to keep it from exiting, because then the perl code keeps running.
And finally, what if I wanted to interpret a perl script? Then I don't have control over whether it wants to exit the perl code
So how do I get exit() to exit perl but not C?
Here's the full test code you can run:
#include <stdio.h> #include <signal.h> #include <EXTERN.h> /* from the Perl distribution */ #include <perl.h> /* from the Perl distribution */ static PerlInterpreter *my_perl; /*** The Perl interpreter ***/ void cleanup(void); //let perl handle it void signal_handler(int signum){ printf("got signal %d\n", signum); } int main(int argc, char **argv, char **env){ signal(SIGINT, signal_handler); PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; char *embedding[] = { "", "-e", "0" }; perl_parse(my_perl, NULL, 3, embedding, NULL); printf("\n----- RUNNING\n"); const char perlcode[] = "sub doubler {" " return $_[0] * 2 if $#_ == 0;" " print STDERR \"doubler() Error, wrong number of args\\n\";" " exit(-1);" "}" "print \"Start perl code\\n\";" "print \"Doubler of 42: \".doubler(42).\"\\n\";" "print \"Doubler of <missing arg>: \".doubler().\"\\n\";" "print \"Done\\n\";" ; SV *ret = eval_pv(perlcode, FALSE); printf("\n----- DONE RUNNING\n"); if( SvTRUE(ERRSV) ){ fprintf(stderr, "%s : eval_sv() has failed with:\n%s\nfor the code:\n%s\n", argv[0], SvPVx_nolen(ERRSV), perlcode); cleanup(); exit(1); } printf("%s : done.\n", argv[0]); exit(EXIT_SUCCESS); } void cleanup(void){ perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
|
---|