do language plperl $$ elog(NOTICE, ${^TAINT}); $$;
 NOTICE:  0
 CONTEXT:  PL/Perl anonymous code block
+-- test recovery after "die"
+create or replace function just_die() returns void language plperl AS $$
+die "just die";
+$$;
+select just_die();
+ERROR:  just die at line 2.
+CONTEXT:  PL/Perl function "just_die"
+create or replace function die_caller() returns int language plpgsql as $$
+BEGIN
+  BEGIN
+    PERFORM just_die();
+  EXCEPTION WHEN OTHERS THEN
+    RAISE NOTICE 'caught die';
+  END;
+  RETURN 1;
+END;
+$$;
+select die_caller();
+NOTICE:  caught die
+ die_caller 
+------------
+          1
+(1 row)
+
+create or replace function indirect_die_caller() returns int language plperl as $$
+my $prepared = spi_prepare('SELECT die_caller() AS fx');
+my $a = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
+my $b = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
+return $a + $b;
+$$;
+select indirect_die_caller();
+NOTICE:  caught die
+CONTEXT:  SQL statement "SELECT die_caller() AS fx"
+PL/Perl function "indirect_die_caller"
+NOTICE:  caught die
+CONTEXT:  SQL statement "SELECT die_caller() AS fx"
+PL/Perl function "indirect_die_caller"
+ indirect_die_caller 
+---------------------
+                   2
+(1 row)
+
 
    Datum       retval;
    plperl_call_data *save_call_data = current_call_data;
    plperl_interp_desc *oldinterp = plperl_active_interp;
+   plperl_call_data this_call_data;
+
+   /* Initialize current-call status record */
+   MemSet(&this_call_data, 0, sizeof(this_call_data));
+   this_call_data.fcinfo = fcinfo;
 
    PG_TRY();
    {
-       current_call_data = NULL;
+       current_call_data = &this_call_data;
        if (CALLED_AS_TRIGGER(fcinfo))
            retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
        else
    }
    PG_CATCH();
    {
-       if (current_call_data && current_call_data->prodesc)
-           decrement_prodesc_refcount(current_call_data->prodesc);
+       if (this_call_data.prodesc)
+           decrement_prodesc_refcount(this_call_data.prodesc);
        current_call_data = save_call_data;
        activate_interpreter(oldinterp);
        PG_RE_THROW();
    }
    PG_END_TRY();
 
-   if (current_call_data && current_call_data->prodesc)
-       decrement_prodesc_refcount(current_call_data->prodesc);
+   if (this_call_data.prodesc)
+       decrement_prodesc_refcount(this_call_data.prodesc);
    current_call_data = save_call_data;
    activate_interpreter(oldinterp);
    return retval;
    plperl_proc_desc desc;
    plperl_call_data *save_call_data = current_call_data;
    plperl_interp_desc *oldinterp = plperl_active_interp;
+   plperl_call_data this_call_data;
    ErrorContextCallback pl_error_context;
 
+   /* Initialize current-call status record */
+   MemSet(&this_call_data, 0, sizeof(this_call_data));
+
    /* Set up a callback for error reporting */
    pl_error_context.callback = plperl_inline_callback;
    pl_error_context.previous = error_context_stack;
    desc.nargs = 0;
    desc.reference = NULL;
 
+   this_call_data.fcinfo = &fake_fcinfo;
+   this_call_data.prodesc = &desc;
+   /* we do not bother with refcounting the fake prodesc */
+
    PG_TRY();
    {
        SV         *perlret;
 
-       current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
-       current_call_data->fcinfo = &fake_fcinfo;
-       current_call_data->prodesc = &desc;
-       /* we do not bother with refcounting the fake prodesc */
+       current_call_data = &this_call_data;
 
        if (SPI_connect() != SPI_OK_CONNECT)
            elog(ERROR, "could not connect to SPI manager");
    ReturnSetInfo *rsi;
    ErrorContextCallback pl_error_context;
 
-   /*
-    * Create the call_data before connecting to SPI, so that it is not
-    * allocated in the SPI memory context
-    */
-   current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
-   current_call_data->fcinfo = fcinfo;
-
    if (SPI_connect() != SPI_OK_CONNECT)
        elog(ERROR, "could not connect to SPI manager");
 
    HV         *hvTD;
    ErrorContextCallback pl_error_context;
 
-   /*
-    * Create the call_data before connecting to SPI, so that it is not
-    * allocated in the SPI memory context
-    */
-   current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
-   current_call_data->fcinfo = fcinfo;
-
    /* Connect to SPI manager */
    if (SPI_connect() != SPI_OK_CONNECT)
        elog(ERROR, "could not connect to SPI manager");
 
 
 -- make sure we don't choke on readonly values
 do language plperl $$ elog(NOTICE, ${^TAINT}); $$;
+
+-- test recovery after "die"
+
+create or replace function just_die() returns void language plperl AS $$
+die "just die";
+$$;
+
+select just_die();
+
+create or replace function die_caller() returns int language plpgsql as $$
+BEGIN
+  BEGIN
+    PERFORM just_die();
+  EXCEPTION WHEN OTHERS THEN
+    RAISE NOTICE 'caught die';
+  END;
+  RETURN 1;
+END;
+$$;
+
+select die_caller();
+
+create or replace function indirect_die_caller() returns int language plperl as $$
+my $prepared = spi_prepare('SELECT die_caller() AS fx');
+my $a = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
+my $b = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
+return $a + $b;
+$$;
+
+select indirect_die_caller();