From 803bd7c91c63f8f263bed592a33b10cf69f567cf Mon Sep 17 00:00:00 2001 From: David Mitchell Date: Fri, 22 Mar 2019 15:43:56 +0000 Subject: fix leak in BEGIN { threads->new(...) } Normally by the time we reach perl_destruct(), PL_parser should be null due to having its original (null) value restored by SAVEt_PARSER during leaving scope (usually before run-time starts in fact). But if a thread is created within a BEGIN block, the parser is duped, but the SAVEt_PARSER savestack entry isn't. So PL_parser never gets cleaned up. Clean it up in perl_destruct() instead. This is a bit of a hack. --- perl.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/perl.c b/perl.c index cdefa99018..1ef425bb25 100644 --- a/perl.c +++ b/perl.c @@ -668,6 +668,21 @@ perl_destruct(pTHXx) FREETMPS; assert(PL_scopestack_ix == 0); + /* normally when we get here, PL_parser should be null due to having + * its original (null) value restored by SAVEt_PARSER during leaving + * scope (usually before run-time starts in fact). + * But if a thread is created within a BEGIN block, the parser is + * duped, but the SAVEt_PARSER savestack entry isn't. So PL_parser + * never gets cleaned up. + * Clean it up here instead. This is a bit of a hack. + */ + if (PL_parser) { + /* stop parser_free() stomping on PL_curcop */ + PL_parser->saved_curcop = PL_curcop; + parser_free(PL_parser); + } + + /* Need to flush since END blocks can produce output */ /* flush stdout separately, since we can identify it */ #ifdef USE_PERLIO -- cgit v1.2.1