mwrap (Perl version) user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
From: ew <e@80x24.org>
To: mwrap-perl@80x24.org
Cc: Eric Wong <e@80x24.org>
Subject: [PATCH] implement SrcLoc::each to walk all allocations
Date: Thu, 21 Nov 2019 23:04:05 +0000	[thread overview]
Message-ID: <20191121230405.1965-1-e@80x24.org> (raw)

From: Eric Wong <e@80x24.org>

Add some cautionary notes around exposing alloc_hdr.
---
 Mwrap.xs  | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 t/mwrap.t | 22 ++++++++++++++++++++++
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/Mwrap.xs b/Mwrap.xs
index 09d5581..6d3c6d2 100644
--- a/Mwrap.xs
+++ b/Mwrap.xs
@@ -188,7 +188,7 @@ static char *int2str(unsigned num, char *dst, size_t * size)
 	return NULL;
 }
 
-/* allocated via real_malloc/real_free */
+/* allocated via real_malloc, immortal for safety reasons */
 struct src_loc {
 	pthread_mutex_t *mtx;
 	size_t total;
@@ -207,7 +207,10 @@ struct src_loc {
  */
 typedef struct src_loc * Devel__Mwrap__SrcLoc;
 
-/* every allocation has this in the header, maintain alignment with malloc  */
+/*
+ * Every allocation has this in the header, maintain alignment with malloc
+ * Do not expose this to Perl code because of use-after-free concerns.
+ */
 struct alloc_hdr {
 	struct cds_list_head anode; /* <=> src_loc.allocs */
 	union {
@@ -940,3 +943,50 @@ OUTPUT:
 	RETVAL
 CLEANUP:
 	--locating;
+
+void
+src_loc_each(self, min, cb)
+	Devel::Mwrap::SrcLoc self;
+	size_t min;
+	SV *cb;
+PREINIT:
+	struct alloc_hdr *h;
+	bool err = false;
+CODE:
+	++locating;
+	rcu_read_lock();
+	cds_list_for_each_entry_rcu(h, &self->allocs, anode) {
+		size_t size = uatomic_read(&h->size);
+
+		if (size > min) {
+			dSP;
+			ENTER;
+			SAVETMPS;
+
+			PUSHMARK(SP);
+
+			/*
+			 * note: we MUST NOT expose alloc_hdr to Perl code
+			 * since that opens us up to use-after-free
+			 */
+			XPUSHs(sv_2mortal(newSVuv(size)));
+			PUTBACK;
+
+			call_sv(cb, G_DISCARD|G_EVAL);
+
+			SPAGAIN;
+			if (SvTRUE(ERRSV))
+				err = true;
+
+			FREETMPS;
+			LEAVE;
+			if (err)
+				break;
+			assert(rcu_read_ongoing());
+		}
+	}
+	if (SvTRUE(ERRSV))
+		croak(NULL);
+CLEANUP:
+	rcu_read_unlock();
+	--locating;
diff --git a/t/mwrap.t b/t/mwrap.t
index 8806847..661a90a 100644
--- a/t/mwrap.t
+++ b/t/mwrap.t
@@ -88,6 +88,28 @@ Devel::Mwrap::each($nbytes, sub { push @keep, @_ });
 scalar(@keep) == 0 or die "::reset did not work";
 EOF
 
+mwrap_run('Devel::Mwrap::SrcLoc::each', {}, '-e', <<'EOF');
+open my $zero, '<', '/dev/zero' or die "open /dev/zero: $!";
+my @keep;
+my $nr = 10;
+my $nbytes = 1024 * 10;
+sub do_read () {
+	sysread($zero, my $buf, $nbytes);
+	# this forces us to allocate a new buf with every call
+	pop @keep;
+	push @keep, $buf;
+}
+for (1..$nr) { do_read() }
+my $loc = Devel::Mwrap::get('-e:6');
+$loc && $loc->total >= ($nbytes * $nr) or die "wrong line or bad stats";
+my @sl_each;
+$loc->each($nbytes, sub { push @sl_each, \@_ });
+my $n = scalar(@sl_each);
+$n == 1 or die "SrcLoc::each returned unexpected: $n";
+$sl_each[0]->[0] >= $nbytes or die "$sl_each[0]->[0] < $nbytes";
+EOF
+diag slurp($out);
+
 done_testing();
 
 sub slurp {

                 reply	other threads:[~2019-11-21 23:04 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191121230405.1965-1-e@80x24.org \
    --to=e@80x24.org \
    --cc=mwrap-perl@80x24.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mwrap-perl.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).