develooper Front page | perl.perl5.porters | Postings from December 2017

Debugging leaked scalars and cyclic references with the SpiderMonkeyGC

Thread Next
From:
Pip Cet
Date:
December 11, 2017 19:09
Subject:
Debugging leaked scalars and cyclic references with the SpiderMonkeyGC
Message ID:
CAOqdjBdPvK-+u4xB2oi7-P5BVmEmoLU3xiMK53pFjTQkcPo_Zw@mail.gmail.com
Hello everyone,
as an experiment, I've modified Perl to use the SpiderMonkey garbage
collector in addition to Perl's own reference-counting.  That allowed
me to detect two places in which SVs were leaked (#132545 and
#132548); it also detects cyclic references, and I'm planning to
extend it to detect use-after-free errors and issues caused by our
non-refcounted stack.

The current approach is to add a JS::Value to each SV, which points
back to the SV. This is inefficient, but works. Garbage collection is
disabled during parsing, and while an op is executed, but enabled
between ops, so no C stack rooting is needed in the main part of Perl.

Most of this patch is the tracing algorithm, which is boring to read,
was boring to write, and is probably incomplete; apart from that,
there are just a few lines of code.

Note that while the SpiderMonkey library is itself multi-threaded, it
can only be used from a single thread; this means that ithreads are
incompatible with this patch.

Also note that as the SpiderMonkey library unfortunately does not
export AutoSuppressGC, I had to hack in a hard-coded offset, so it's
likely this code will break soon when SpiderMonkey changes its context
struct (it will also only work on x86_64 and Linux, most likely).

No attempt has been made to make weak references or DESTROY methods work.

There is one known issue: XSUBs store an ANY pointer, which might be a
referenced SV or a random pointer. Unfortunately, most code uses
any_ptr rather than any_sv even if the argument is an SV, so my code
currently assumes any_ptr is an SV, and will break if it's a random
pointer to something the garbage collector doesn't know about.

Build instructions:

* Check out the "perl" branch from https://github.com/pipcet/mozilla

* configure it by running, in the js/src directory:

# autoconf2.13
# ./configure --enable-debug --enable-gczeal --disable-tests

* make

* copy the js/src/dist subdirectory to /path/to/js/

* Check out the "smin" branch from https://github.com/pipcet/perl.

* Regenerate miniperlmain.c with regen/miniperlmain.pl

* set the path to the SpiderMonkey runtime with

# export LD_LIBRARY_PATH=/path/to/js/dist/bin:$LD_LIBRARY_PATH

* Configure with something like

# ./Configure -d -Dusedevel -Dcc=c++ -Dlibs='-lpthread -pthread -lnsl
-ldl -lm -lcrypt -lutil -lc -L/path/to/js/dist/bin -lmozjs-59a1
-Wl,--whole-archive /path/to/js/mozglue/build/libmozglue.a
-Wl,--no-whole-archive' -Dccflags='-fwrapv -fno-strict-aliasing -pipe
-fstack-protector-strong -I/usr/local/include
-I/path/to/js/dist/include -g3 -ggdb -D_FORTIFY_SOURCE=2'

(obviously replacing the paths to the SpiderMonkey libraries as appropriate).

* (Optional) set JS_GC_ZEAL to cause more GCs

# export JS_GC_ZEAL=2,10

* Run make
* test with a leaky program

# ./perl -e '{my $a; my $b; $a = \$b; $b = \$a;} while(1) { $x[$y++] = 3; }'

Ideally, you should get a segmentation fault and an error message.

If you can make a valid program produce a segmentation fault, you
probably found a bug in the tracer. Please report this to me at
pipcet@gmail.com.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About