# New Ticket Created by Nicholas Clark # Please include the string: [perl #32137] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=32137 >
--- osname= linux osvers= 2.4.21-14.elsmp arch= i386-linux-thread-multi cc= gcc 3.2.3 20030502 (Red Hat Linux 3.2.3-37) --- Flags: category=core severity=high ack=no --- I have evidence that DOD runs can miss noticing local variable pointers to live objects on x86 Linux. This is happening while running ponie, but the problem is during a single call to string_make. The gdb traces are from a copy of the parrot source code which has had a few debugging printf()s and static variables added, but the problem shows up with vanilla parrot source code. Specifically this variable at the top of string_make: STRING *s = NULL; (which experimentally is "volatile" in my copy, but the failure is the same without) gets assigned a header by new_string_header, called at line 789 (or so) of string.c: (gdb) new_string_header (interpreter=0x844f388, flags=0) at src/headers.c:355 355 PObj_get_FLAGS(string) |= flags | PObj_is_string_FLAG; (gdb) 357 return string; (gdb) p string $4 = (STRING *) 0x85ba81c string_make then gets to the call to Parrot_allocate_string which calls into mem_allocate, which triggers a DOD run: 656 PObj_bufstart(str) = mem_allocate(interpreter, &req_size, pool, (gdb) mem_allocate (interpreter=0x844f388, req_size=0xbfff8ca0, pool=0x844fb90, align_1=15) at src/resources.c:128 128 size_t size = aligned_size(*req_size, align_1); (gdb) aligned_size (size=9, align=15) at src/resources.c:111 111 if (size < sizeof(void *)) (gdb) 116 size += sizeof(struct Buffer_Tail); (gdb) 119 size = (size + align) & ~align; (gdb) 120 return size; (gdb) 121 } (gdb) mem_allocate (interpreter=0x844f388, req_size=0xbfff8ca0, pool=0x844fb90, align_1=15) at src/resources.c:131 131 if (pool->top_block == NULL) { (gdb) 135 if (pool->top_block->free < size) { (gdb) p pool->top_block $7 = (struct Memory_Block *) 0xb5483008 (gdb) p *pool->top_block $8 = {free = 0, size = 655360, prev = 0x0, next = 0x0, start = 0xb5483020 "(?^\b????\001", top = 0xb5523020 ""} (gdb) s 142 Parrot_do_dod_run(interpreter, DOD_trace_stack_FLAG); At which point I let the DOD run go in one. My copy of gc_mc_add_free_object has some printf()s in it, with a counter hard coded to trigger just here: static void gc_ms_add_free_object(Interp *interpreter, struct Small_Object_Pool *pool, void *to_add) { static int counter; if (pool->object_size==36 && count > 3 && counter < 5) { printf ("Add '%s' %p %d %p\n", pool->name, to_add, pool->num_free_objects, pool->free_list); counter++; } *(void **)to_add = pool->free_list; pool->free_list = to_add; if (problem_seen && to_add == problem) { printf ("Adding problem %p to free %d\n", problem, problem_seen); } } (gdb) n Add 'string_header' 0x85ba81c 2962 0x85ba7f8 Add 'string_header' 0x85ba840 2962 0x85ba81c Add 'string_header' 0x85ba864 2962 0x85ba840 Add 'string_header' 0x85ba888 2962 0x85ba864 Add 'string_header' 0x85ba8ac 2962 0x85ba888 Note that 0x85ba81c, the first thing to be added, is the string header I mentioned earlier, pointed to by s 2 frames up. 145 if (pool->compact) { (gdb) up #1 0x0821c772 in Parrot_allocate_string (interpreter=0x844f388, str=0x85ba81c, size=9) at src/resources.c:656 656 PObj_bufstart(str) = mem_allocate(interpreter, &req_size, pool, (gdb) up #2 0x08173067 in string_make (interpreter=0x844f388, buffer=0x83a50b0, len=9, encoding_name=0x83b2038 "iso-8859-1", flags=0) at src/string.c:829 829 Parrot_allocate_string(interpreter, s, len); (gdb) p s $9 = (volatile STRING *) 0x85ba81c (gdb) where #0 mem_allocate (interpreter=0x844f388, req_size=0xbfff8ca0, pool=0x844fb90, align_1=15) at src/resources.c:145 #1 0x0821c772 in Parrot_allocate_string (interpreter=0x844f388, str=0x85ba81c, size=9) at src/resources.c:656 #2 0x08173067 in string_make (interpreter=0x844f388, buffer=0x83a50b0, len=9, encoding_name=0x83b2038 "iso-8859-1", flags=0) at src/string.c:829 #3 0x08172dfa in string_from_cstring (interpreter=0x844f388, buffer=0x83a50b0, len=0) at src/string.c:658 #4 0x081b9d97 in Parrot_PMC_typenum (interp=0x844f388, class=0x83a50b0 "Perl5NULL") at src/extend.c:600 #5 0x080d20dd in S_new_SV () at sv.c:164 So why is the x86 stack walking code missing the pointer to 0x85ba81c held in local variable s 2 stack frames higher? It's a bit of a bugger as it causes a SEGV. :-( Looks like the configuration information needs a bit more: gcc (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-42) Linux switch.work.fotango.com 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 i686 i686 i386 GNU/Linux libc-2.3.2.so Nicholas Clark PS It's occurred to me that this constant calling of Parrot_PMC_typenum without caching (or precomputing) the result is woefully inefficient, but I'd like this problem resolved before I change anything. And I'm stuck. --- Summary of my parrot 0.1.1 configuration: configdate='Tue Oct 19 11:14:39 2004' Platform: osname=linux, archname=i686-linux jitcapable=1, jitarchname=i386-linux, jitosname=LINUX, jitcpuarch=i386 execcapable=1 perl=/usr/local/perl-5.8.5/bin/perl Compiler: cc='cc', ccflags=' -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', Linker and Libraries: ld='cc', ldflags=' -L/usr/local/lib', cc_ldflags='', libs='-lnsl -ldl -lm -lcrypt -lutil -lpthread -lrt' Dynamic Linking: share_ext='.so', ld_share_flags='-shared -L/usr/local/lib -fPIC', load_ext='.so', ld_load_flags='-shared -L/usr/local/lib -fPIC' Types: iv=long, intvalsize=4, intsize=4, opcode_t=long, opcode_t_size=4, ptrsize=4, ptr_alignment=1 byteorder=1234, nv=double, numvalsize=8, doublesize=8 --- Environment: HOME LANG LANGUAGE LD_LIBRARY_PATH LOGDIR PATH SHELL