# New Ticket Created by Mark Glines
# Please include the string: [perl #43102]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=43102 >
While testing/trying to fix RT #42938, I noticed an additional test
failure in t/pmc/threads.t. Test 7 crashes with a signal 11
(segmentation fault), on my Gentoo Linux-x86 box. This is with svn
r18722.
I've stared at gdb, header files and preprocessor output for a while.
I'll include all the info I think is relevant.
t/pmc/threads....NOK 7/20
# Failed test (t/pmc/threads.t at line 290)
# Exited with error code: [SIGNAL 11]
# Received:
# thread
#
# Expected:
# /(done\nthread\n)|(thread\ndone\n)/
#
Starting program: /home/paranoid/parrot/parrot detach.pir
[Thread debugging using libthread_db enabled]
[New Thread -1227352400 (LWP 25907)]
warning: Lowest section in /usr/lib/libicudata.so.36 is .hash at 000000d4
[New Thread -1227355216 (LWP 25910)]
[New Thread -1235747920 (LWP 25911)]
[New Thread -1244140624 (LWP 25912)]
thread
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1244140624 (LWP 25912)]
0xb7da53ab in clear_cow (interp=0x82256f0, pool=0x82285c8, cleanup=1)
at src/gc/dod.c:469
469 *refcount = 0;
(gdb) print refcount
$1 = (INTVAL * const) 0xb7eb4b41
The code in question:
INTVAL * const refcount = PObj_bufrefcountptr(b);
*refcount = 0;
Which expands to:
INTVAL * const refcount = (&(((Buffer_alloc_unit *)((char
*) (b)->obj.u._b._bufstart - (((size_t) &((Buffer_alloc_unit
*)0)->buffer))))->ref_ count));
*refcount = 0;
(gdb) bt
#0 0xb7da53ab in clear_cow (interp=0x82256f0, pool=0x82285c8,
cleanup=1) at src/gc/dod.c:469
#1 0xb7da30ae in sweep_cb_buf (interp=0x82256f0, pool=0x82285c8, flag=6,
arg=0x0) at src/headers.c:691
#2 0xb7da2f56 in Parrot_forall_header_pools (interp=0x82256f0, flag=6,
arg=0x0, func=0xb7da3080 <sweep_cb_buf>) at src/headers.c:640
#3 0xb7da318f in Parrot_destroy_header_pools (interp=0x82256f0)
at src/headers.c:732
#4 0xb7d490bb in Parrot_really_destroy (interp=0x82256f0, exit_code=0,
arg=0x0) at src/inter_create.c:390
#5 0xb7dc5399 in thread_func (arg=0x83c0c28) at src/thread.c:403
#6 0xb7b6f380 in start_thread () from /lib/libpthread.so.0
#7 0xb6f1554e in clone () from /lib/libc.so.6
(gdb) print *b
$3 = {obj = {u = {_b = {_bufstart = 0xb7eb4b45, _buflen = 6}, _ptrs = {
_struct_val = 0xb7eb4b45, _pmc_val = 0x6}, _i = {
_int_val = -1209316539, _int_val2 = 6},
_num_val = 1.425648877988937e-313, _string_val = 0xb7eb4b45},
flags = 196864}}
(gdb) print ((char*)(b->obj.u._b._bufstart))
$4 = 0xb7eb4b45 "parrot"
So it looks to me like it's expecting to find a refcount integer right
before the buffer, in memory. But the buffer is a null-terminated
string, packed in memory with another string directly preceding it...
no refcount integer!
Here's a hexdump of the memory:
b7eb4b30 75 70 2e 63 00 28 73 65 6c 66 29 2d 3e 70 6d 63 |up.c~(self)->pmc|
b7eb4b40 5f 65 78 74 00 70 61 72 72 6f 74 00 00 00 00 00 |_ext~parrot~~~~~|
_bufstart pointer: ^^ ^
(in the ASCII part of that hexdump, "~" means null.)
I'm in way over my head here, but I see 3 warning signs telling me
this is a bug:
1. The SIGSEGV, obviously.
2. The lack of refcount integer where the code expects to find one.
3. The buffer isn't dword-aligned. (Aren't allocated buffers aligned
by default? Could this be a constant string defined at compile time,
instead?)
I also get an intermittant failure of test 5 (occurs about once every 5
runs). I believe it is likely to be caused by the same issue, but I
have not debugged it to the same extent.
# Failed test (t/pmc/threads.t at line 204)
# Exited with error code: [SIGNAL 11]
# Received:
# start 1
# in thread
# done
#
# Expected:
# start 1
# in thread
# done
Mark