Skip to content

ASAN and threads don't play well together on Linux with clang #20810

Closed
@jkeenan

Description

@jkeenan

Inspired by some discussion on #p5p, I decided to try to build a perl on Linux (Debian 11) with clang and ASAN. I make no claim to knowing what I'm doing in ASAN territory; I did not have any clear idea of what the results would be. I found that when I configured with arguments similar to those used in George Greer's smoke-testing reports (e.g., https://perl5.test-smoke.org/report/5030661), I was able to get at least as far as building miniperl with ASAN and unthreaded builds -- but not with threaded builds.

Threaded builds

I've tried the following at tags v5.34.0 and v5.36.0 as well as blead.

sh ./Configure -des -Dusedevel -Dcc=clang \
-Accflags="-g -fno-omit-frame-pointer -fsanitize=address  -fno-common -fsanitize-blacklist=`pwd`/asan_ignore" -Aldflags="-fsanitize=address" \
-Duseithreads \
&& make miniperl

Compilation failed like this:

...
    opmini.o perlmini.o  gv.o toke.o perly.o pad.o regcomp.o dump.o util.o mg.o reentr.o mro_core.o keywords.o hv.o av.o run.o pp_hot.o sv.o pp.o scope.o pp_ctl.o pp_sys.o doop.o doio.o regexec.o utf8.o taint.o deb.o universal.o globals.o perlio.o numeric.o mathoms.o locale.o pp_pack.o pp_sort.o caretx.o dquote.o time64.o  miniperlmain.o  -lpthread -lnsl -ldl -lm -lcrypt -lutil -lc 
./miniperl -w -Ilib -Idist/Exporter/lib -MExporter -e '<?>' || sh -c 'echo >&2 Failed to build miniperl.  Please run make minitest; exit 1'

=================================================================
==747495==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 4072 byte(s) in 1 object(s) allocated from:
    #0 0x49ce02 in calloc (/home/jkeenan/gitwork/perl/miniperl+0x49ce02)

... followed by a long list of direct and indirect leaks.

Unthreaded builds

If I simply dropped the -Duseithreads from the configuration, miniperl would build on v5.34.0, v5.36.0 and blead (v5.37.8-172-gd0613d9c78).

$ clang --version | head -1
Debian clang version 11.0.1-2

On v5.34.0, in the ASAN unthreaded build, I got 2 test failures in make test_harness:

Test Summary Report
-------------------
re/pat.t                                                           (Wstat: 9 Tests: 108 Failed: 0)
  Non-zero wait status: 9
  Parse errors: Bad plan.  You planned 1022 tests but ran 108.
../cpan/Encode/t/mime-header.t                                     (Wstat: 9 Tests: 207 Failed: 0)
  Non-zero wait status: 9
  Parse errors: Bad plan.  You planned 266 tests but ran 207.
Files=2667, Tests=1185872, 2052 wallclock secs (205.45 usr 77.94 sys + 1519.58 cusr 382.20 csys = 2185.17 CPU)
Result: FAIL
make: *** [makefile:839: test_harness] Error 2

However, when I tested just those two files, I got a PASS.

$ cd t; TEST_JOBS=1 ./perl harness re/pat.t ../cpan/Encode/t/mime-header.t; cd -
re/pat.t ........................ ok         
../cpan/Encode/t/mime-header.t .. ok       
All tests successful.
Files=2, Tests=1288, 119 wallclock secs ( 0.20 usr  0.02 sys + 33.00 cusr 85.63 csys = 118.85 CPU)
Result: PASS

(I didn't completely test v5.36.0.)

On blead, in the ASAN unthreaded build, I got 4 test failures:

$ git describe; ./perl -Ilib -V:config_args
v5.37.8-172-gd0613d9c78
config_args='-des -Dusedevel -Dcc=clang -Accflags=-g -fno-omit-frame-pointer -fsanitize=address  -fno-common -fsanitize-blacklist=/home/jkeenan/gitwork/perl/asan_ignore -Aldflags=-fsanitize=address';
...
Test Summary Report
-------------------
re/bigfuzzy_not_utf8.t                                             (Wstat: 0 Tests: 1 Failed: 1)
  Failed test:  1
re/pat.t                                                           (Wstat: 9 (Signal: KILL) Tests: 276 Failed: 0)
  Non-zero wait status: 9
  Parse errors: Bad plan.  You planned 1230 tests but ran 276.
re/pat_psycho.t                                                    (Wstat: 9 (Signal: KILL) Tests: 1 Failed: 0)
  Non-zero wait status: 9
  Parse errors: Bad plan.  You planned 15 tests but ran 1.
../lib/warnings.t                                                  (Wstat: 0 Tests: 940 Failed: 1)
  Failed test:  380
Files=2738, Tests=1180601, 1983 wallclock secs (193.95 usr 69.90 sys + 1533.20 cusr 347.26 csys = 2144.31 CPU)
Result: FAIL
Finished test run at Tue Feb 14 23:59:37 2023.
make: *** [makefile:865: test_harness] Error 2

Re-running just the failing files, I got 3 PASSes and 1 FAIL.

$ cd t; TEST_JOBS=1 ./perl harness re/bigfuzzy_not_utf8.t re/pat.t re/pat_psycho.t ../lib/warnings.t; cd -
re/bigfuzzy_not_utf8.t .. ok   
re/pat.t ................ ok         
re/pat_psycho.t ......... ok  
../lib/warnings.t ....... 356/940 FILE: lib/warnings/class ; line 13
PROG: 
# constructor warnings
use v5.36;
use feature 'class';
no warnings 'experimental::class';
class C { }
C->new();
eval { C->new('foo') }; # suppress error
EXPECTED:
Odd number of arguments passed to "C" constructor at - line 7.
GOT:
Odd number of arguments passed to "C" constructor at - line 7.

=================================================================
==857841==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x4b1bcd in malloc (/home/jkeenan/gitwork/perl/perl+0x4b1bcd)
    #1 0x749e54 in Perl_safesysmalloc /home/jkeenan/gitwork/perl/util.c:161:21
    #2 0x7949d7 in Perl_newSVobject /home/jkeenan/gitwork/perl/class.c:40:5
    #3 0x796234 in injected_constructor /home/jkeenan/gitwork/perl/class.c:162:20
    #4 0x7dea53 in Perl_pp_entersub /home/jkeenan/gitwork/perl/pp_hot.c:5518:9
    #5 0x7bb319 in Perl_runops_standard /home/jkeenan/gitwork/perl/run.c:41:26
    #6 0x55639e in S_run_body /home/jkeenan/gitwork/perl/perl.c
    #7 0x555751 in perl_run /home/jkeenan/gitwork/perl/perl.c:2722:9
    #8 0x4e19ae in main /home/jkeenan/gitwork/perl/perlmain.c:127:9
    #9 0x7f6e22f5ad09 in __libc_start_main csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
# Failed test 380 - test from lib/warnings/class at line 13 at lib/warnings/class line 13
../lib/warnings.t ....... 933/940 #
# Note: 'run_multiple_progs' run has one or more failures
#        you can consider setting the environment variable
#        PERL_TEST_ABORT_FIRST_FAILURE=1 before running the test
#        to stop on the first error.
#
../lib/warnings.t ....... Failed 1/940 subtests 
	(less 1 skipped subtest: 938 okay)

Test Summary Report
-------------------
../lib/warnings.t     (Wstat: 0 Tests: 940 Failed: 1)
  Failed test:  380
Files=4, Tests=2186, 126 wallclock secs ( 0.57 usr  0.09 sys + 46.67 cusr 78.61 csys = 125.94 CPU)

To what extent are these results plausible? First, failure to get as far as miniperl with clang, ASAN and threads?

Second, inconsistent test failures with ASAN but without threads?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions