summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2019-03-22 15:43:56 +0000
committerDavid Mitchell <davem@iabyn.com>2019-03-25 12:35:27 +0000
commit803bd7c91c63f8f263bed592a33b10cf69f567cf (patch)
tree5281ed1d9c1183dc31eee59a3484a9345ab83512
parent75bb5aa48dfcf930533cd069393fc8a45e4ece18 (diff)
downloadperl-803bd7c91c63f8f263bed592a33b10cf69f567cf.tar.gz
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.
-rw-r--r--perl.c15
1 files changed, 15 insertions, 0 deletions
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