which become unreferenced. This is less likely to be successful.
The #define needs a better name.
p4raw-id: //depot/perl@24976
ApR |bool |stashpv_hvname_match|NN const COP *cop|NN const HV *hv
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+p |void |dump_sv_child |SV *sv
+#endif
+
END_EXTERN_C
/*
* ex: set ts=8 sts=4 sw=4 noet:
#define is_gv_magical_sv Perl_is_gv_magical_sv
#endif
#define stashpv_hvname_match Perl_stashpv_hvname_match
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+#ifdef PERL_CORE
+#define dump_sv_child Perl_dump_sv_child
+#endif
+#endif
#define ck_anoncode Perl_ck_anoncode
#define ck_bitop Perl_ck_bitop
#define ck_concat Perl_ck_concat
#define is_gv_magical_sv(a,b) Perl_is_gv_magical_sv(aTHX_ a,b)
#endif
#define stashpv_hvname_match(a,b) Perl_stashpv_hvname_match(aTHX_ a,b)
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+#ifdef PERL_CORE
+#define dump_sv_child(a) Perl_dump_sv_child(aTHX_ a)
+#endif
+#endif
#define ck_anoncode(a) Perl_ck_anoncode(aTHX_ a)
#define ck_bitop(a) Perl_ck_bitop(aTHX_ a)
#define ck_concat(a) Perl_ck_concat(aTHX_ a)
#define PL_doextract (vTHX->Idoextract)
#define PL_doswitches (vTHX->Idoswitches)
#define PL_dowarn (vTHX->Idowarn)
+#define PL_dumper_fd (vTHX->Idumper_fd)
#define PL_e_script (vTHX->Ie_script)
#define PL_egid (vTHX->Iegid)
#define PL_encoding (vTHX->Iencoding)
#define PL_Idoextract PL_doextract
#define PL_Idoswitches PL_doswitches
#define PL_Idowarn PL_dowarn
+#define PL_Idumper_fd PL_dumper_fd
#define PL_Ie_script PL_e_script
#define PL_Iegid PL_egid
#define PL_Iencoding PL_encoding
taken out of blead soon, and relevant prototypes changed. */
PERLVARI(Ifdscript, int, -1) /* fd for script */
PERLVARI(Isuidscript, int, -1) /* fd for suid script */
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+/* File descriptor to talk to the child which dumps scalars. */
+PERLVARI(Idumper_fd, int, -1)
+#endif
/* New variables must be added to the very end, before this comment,
* for binary compatibility (the offsets of the old members must not change).
* (Don't forget to add your variable also to perl_clone()!)
* XSUB.h provides wrapper functions via perlapi.h that make this
* irrelevant, but not all code may be expected to #include XSUB.h.
*/
-
return 0;
}
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+void
+Perl_dump_sv_child(pTHX_ SV *sv)
+{
+ ssize_t got;
+ int sock = PL_dumper_fd;
+ SV *target;
+
+ if(sock == -1)
+ return;
+
+ PerlIO_flush(Perl_debug_log);
+
+ got = write(sock, &sv, sizeof(sv));
+
+ if(got < 0) {
+ perror("Debug leaking scalars parent write failed");
+ abort();
+ }
+ if(got < sizeof(target)) {
+ perror("Debug leaking scalars parent short write");
+ abort();
+ }
+
+ got = read(sock, &target, sizeof(target));
+
+ if(got < 0) {
+ perror("Debug leaking scalars parent read failed");
+ abort();
+ }
+ if(got < sizeof(target)) {
+ perror("Debug leaking scalars parent short read");
+ abort();
+ }
+
+ if (target != sv) {
+ perror("Debug leaking scalars parent target != sv");
+ abort();
+ }
+}
+#endif
+
/*
=for apidoc perl_destruct
volatile int destruct_level; /* 0=none, 1=full, 2=full with checks */
HV *hv;
#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
- int sock;
pid_t child;
#endif
abort();
}
if (!child) {
+ int sock = fd[1];
/* We are the child */
close(fd[0]);
- sock = fd[1];
while (1) {
SV *target;
}
_exit(0);
}
- sock = fd[0];
+ PL_dumper_fd = fd[0];
close(fd[1]);
}
#endif
svend = &sva[SvREFCNT(sva)];
for (sv = sva + 1; sv < svend; ++sv) {
if (SvTYPE(sv) != SVTYPEMASK) {
-#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
- ssize_t got;
- SV *target;
-#endif
-
PerlIO_printf(Perl_debug_log, "leaked: sv=0x%p"
" flags=0x%"UVxf
" refcnt=%"UVuf pTHX__FORMAT "\n"
PL_op_name[sv->sv_debug_optype]: "(none)",
sv->sv_debug_cloned ? " (cloned)" : ""
);
-
#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
- PerlIO_flush(Perl_debug_log);
-
- got = write(sock, &sv, sizeof(sv));
-
- if(got < 0) {
- perror("Debug leaking scalars parent write failed");
- abort();
- }
- if(got < sizeof(target)) {
- perror("Debug leaking scalars parent short write");
- abort();
- }
-
- got = read(sock, &target, sizeof(target));
-
- if(got < 0) {
- perror("Debug leaking scalars parent read failed");
- abort();
- }
- if(got < sizeof(target)) {
- perror("Debug leaking scalars parent short read");
- abort();
- }
+ Perl_dump_sv_child(aTHX_ sv);
#endif
}
}
This seems to be the least effort way of timing out on reaping
its exit status. */
struct timeval waitfor = {4, 0};
+ int sock = PL_dumper_fd;
shutdown(sock, 1);
FD_ZERO(&rset);
#define PL_doswitches (*Perl_Idoswitches_ptr(aTHX))
#undef PL_dowarn
#define PL_dowarn (*Perl_Idowarn_ptr(aTHX))
+#undef PL_dumper_fd
+#define PL_dumper_fd (*Perl_Idumper_fd_ptr(aTHX))
#undef PL_e_script
#define PL_e_script (*Perl_Ie_script_ptr(aTHX))
#undef PL_egid
__attribute__nonnull__(pTHX_2);
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+PERL_CALLCONV void Perl_dump_sv_child(pTHX_ SV *sv);
+#endif
+
END_EXTERN_C
/*
* ex: set ts=8 sts=4 sw=4 noet:
SvREFCNT(sv) = (~(U32)0)/2;
return;
}
- if (ckWARN_d(WARN_INTERNAL))
+ if (ckWARN_d(WARN_INTERNAL)) {
Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
"Attempt to free unreferenced scalar: SV 0x%"UVxf
pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+ Perl_dump_sv_child(aTHX_ sv);
+#endif
+ }
return;
}
if (--(SvREFCNT(sv)) > 0)