I am using the perlembed examples for embedding perl into C code.

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

In reply to Embedded perl: allowing 'exit' in eval_pv without exiting C program by daveola

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":