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();
}
|
|---|