Tcl Source Code

View Ticket
Login
Ticket UUID: 1905797
Title: segfault in oo.test on object destroy for x86_64 arch
Type: Bug Version: obsolete: 8.5.1
Submitter: v_f Created on: 2008-03-02 18:38:42
Subsystem: 35. TclOO Package Assigned To: dkf
Priority: 8 Severity:
Status: Closed Last Modified: 2008-05-12 19:48:59
Resolution: Fixed Closed By: dkf
    Closed on: 2008-05-12 12:48:59
Description:
Executing oo.test on x86_64 results in segmentation fault for test case oo-14.3. See backtrace:

% valgrind --db-attach=yes tclsh oo.test 
==6797== Memcheck, a memory error detector.
==6797== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==6797== Using LibVEX rev 1804, a library for dynamic binary translation.
==6797== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==6797== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==6797== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==6797== For more details, rerun with: -v
==6797== 
==6797== Invalid read of size 4
==6797==    at 0x5D64A29: ReleaseClassContents (tclOO.c:599)
==6797==    by 0x5D64930: ObjectRenamedTrace (tclOO.c:555)
==6797==    by 0x4E5F737: CallCommandTraces (tclBasic.c:2918)
==6797==    by 0x4E5F3CC: Tcl_DeleteCommandFromToken (tclBasic.c:2741)
==6797==    by 0x5D68462: ObjectDestroy (tclOO.c:2140)
==6797==    by 0x5D71FA8: BasicClassMethodInvoke (tclOOMethod.c:315)
==6797==    by 0x5D6A95C: TclOOInvokeContext (tclOOCall.c:218)
==6797==    by 0x5D67D18: TclOOObjectCmdCore (tclOO.c:1895)
==6797==    by 0x5D678D2: PublicObjectCmd (tclOO.c:1756)
==6797==    by 0x4E60813: TclEvalObjvInternal (tclBasic.c:3647)
==6797==    by 0x4E61B08: TclEvalEx (tclBasic.c:4294)
==6797==    by 0x4E6106D: Tcl_EvalEx (tclBasic.c:4000)
==6797==  Address 0x6c346e8 is 8 bytes inside a block of size 248 free'd
==6797==    at 0x4C22B9E: free (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==6797==    by 0x4E5C36D: TclpFree (tclAlloc.c:729)
==6797==    by 0x4E68084: Tcl_Free (tclCkalloc.c:1182)
==6797==    by 0x4F195AC: Tcl_Release (tclPreserve.c:230)
==6797==    by 0x5D64968: ObjectRenamedTrace (tclOO.c:559)
==6797==    by 0x4E5F737: CallCommandTraces (tclBasic.c:2918)
==6797==    by 0x4E5F3CC: Tcl_DeleteCommandFromToken (tclBasic.c:2741)
==6797==    by 0x5D68462: ObjectDestroy (tclOO.c:2140)
==6797==    by 0x5D71FA8: BasicClassMethodInvoke (tclOOMethod.c:315)
==6797==    by 0x5D6A95C: TclOOInvokeContext (tclOOCall.c:218)
==6797==    by 0x5D67D18: TclOOObjectCmdCore (tclOO.c:1895)
==6797==    by 0x5D678D2: PublicObjectCmd (tclOO.c:1756)
==6797== 
==6797== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- y
==6797== starting debugger with cmd: /usr/bin/gdb -nw /proc/6798/fd/1014 6798
GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
Attaching to program: /proc/6798/fd/1014, process 6798
Reading symbols from /usr/lib64/valgrind/amd64-linux/vgpreload_core.so...done.
Loaded symbols for /usr/lib64/valgrind/amd64-linux/vgpreload_core.so
Reading symbols from /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so...done.
Loaded symbols for /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so
Reading symbols from /usr/local/tcl/8.5.1-dbg/lib/libtcl8.5.so...done.
Loaded symbols for /usr/local/tcl/8.5.1-dbg/lib/libtcl8.5.so
Reading symbols from /lib64/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib64/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib64/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /usr/local/tcl/8.5.1-dbg/lib/TclOO0.2a0/libTclOO0.2a0.so...done.
Loaded symbols for /usr/local/tcl/8.5.1-dbg/lib/TclOO0.2a0/libTclOO0.2a0.so
0x0000000005d64a29 in ReleaseClassContents (interp=0x5963d30, oPtr=0x6c2ff18) at ./generic/tclOO.c:599
599             if (!(list[i]->flags & OBJECT_DELETED) && interp != NULL) {
(gdb) p i
$1 = 0
(gdb) bt
#0  0x0000000005d64a29 in ReleaseClassContents (interp=0x5963d30, oPtr=0x6c2ff18) at ./generic/tclOO.c:599
#1  0x0000000005d64931 in ObjectRenamedTrace (clientData=0x6c2ff18, interp=0x5963d30, oldName=0x6c3d030 "::mix", newName=0x0, 
    flags=16512) at ./generic/tclOO.c:555
#2  0x0000000004e5f738 in CallCommandTraces (iPtr=0x5963d30, cmdPtr=0x6c30420, oldName=0x6c3d030 "::mix", newName=0x0, flags=16512)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:2918
#3  0x0000000004e5f3cd in Tcl_DeleteCommandFromToken (interp=0x5963d30, cmd=0x6c30420)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:2741
#4  0x0000000005d68463 in ObjectDestroy (clientData=0x0, interp=0x5963d30, context=0x6c3ce30, objc=2, objv=0x5965ab0)
    at ./generic/tclOO.c:2140
#5  0x0000000005d71fa9 in BasicClassMethodInvoke (clientData=0x5f76940, interp=0x5963d30, context=0x6c3ce30, objc=2, 
    objv=0x5965ab0) at ./generic/tclOOMethod.c:315
#6  0x0000000005d6a95d in TclOOInvokeContext (interp=0x5963d30, contextPtr=0x6c3ce30, objc=2, objv=0x5965ab0)
    at ./generic/tclOOCall.c:218
#7  0x0000000005d67d19 in TclOOObjectCmdCore (oPtr=0x6c2ff18, interp=0x5963d30, objc=2, objv=0x5965ab0, flags=1, 
    cachePtr=0x6c2ffd8, startCls=0x0) at ./generic/tclOO.c:1895
#8  0x0000000005d678d3 in PublicObjectCmd (clientData=0x6c2ff18, interp=0x5963d30, objc=2, objv=0x5965ab0)
    at ./generic/tclOO.c:1756
#9  0x0000000004e60814 in TclEvalObjvInternal (interp=0x5963d30, objc=2, objv=0x5965ab0, command=0x6c2aa4b "mix destroy\n", 
    length=12, flags=0) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:3647
#10 0x0000000004e61b09 in TclEvalEx (interp=0x5963d30, script=0x6c2aa38 "\n    c destroy\n    mix destroy\n", numBytes=31, 
    flags=262144, line=3) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4294
#11 0x0000000004e6106e in Tcl_EvalEx (interp=0x5963d30, script=0x6c2aa38 "\n    c destroy\n    mix destroy\n", numBytes=31, 
    flags=262144) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4000
#12 0x0000000004e62378 in TclEvalObjEx (interp=0x5963d30, objPtr=0x6c2a9d8, flags=262144, invoker=0x0, word=0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4672
#13 0x0000000004e61fd8 in Tcl_EvalObjEx (interp=0x5963d30, objPtr=0x6c2ff18, flags=262144)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4553
#14 0x0000000004f1acca in Tcl_UplevelObjCmd (dummy=0x0, interp=0x5963d30, objc=1, objv=0x59657f0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclProc.c:911
#15 0x0000000004e60814 in TclEvalObjvInternal (interp=0x5963d30, objc=3, objv=0x59657e0, 
    command=0xffffffffffffffff <Address 0xffffffffffffffff out of bounds>, length=-1, flags=0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:3647
#16 0x0000000004ec2e66 in TclExecuteByteCode (interp=0x5963d30, codePtr=0x600c6b8)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclExecute.c:2255
#17 0x0000000004f1bd27 in TclObjInterpProcCore (interp=0x5963d30, procNameObj=0x6c2a418, skip=1, 
    errorProc=0x4f1c431 <MakeProcError>) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclProc.c:1721
#18 0x0000000004f1bc23 in TclObjInterpProc (clientData=0x5d17298, interp=0x5963d30, objc=11, objv=0x5965100)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclProc.c:1615
#19 0x0000000004efed32 in InvokeImportedCmd (clientData=0x5f85b80, interp=0x5963d30, objc=11, objv=0x5965100)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclNamesp.c:1889
#20 0x0000000004e60814 in TclEvalObjvInternal (interp=0x5963d30, objc=11, objv=0x5965100, 
    command=0x59fbfea "test oo-14.3 {OO and mixins and filters - advanced case} -setup {\n    oo::class create mix\n    oo::class create c {\n\tmixin mix\n    }\n    c create i\n} -body {\n    oo::define mix {\n\tmethod foo {} {retur"..., length=353, flags=0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:3647
#21 0x0000000004e61b09 in TclEvalEx (interp=0x5963d30, 
    script=0x59f6b50 "# This file contains a collection of tests for Tcl's built-in object system.\n# Sourcing this file into Tcl runs the tests and generates output for errors.\n# No output means no errors were found.\n#\n# C"..., numBytes=39130, flags=0, 
    line=737) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4294
#22 0x0000000004e6106e in Tcl_EvalEx (interp=0x5963d30, 
    script=0x59f6b50 "# This file contains a collection of tests for Tcl's built-in object system.\n# Sourcing this file into Tcl runs the tests and generates output for errors.\n# No output means no errors were found.\n#\n# C"..., numBytes=39130, flags=0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclBasic.c:4000
#23 0x0000000004ef38dd in Tcl_FSEvalFileEx (interp=0x5963d30, pathPtr=0x599bcb0, encodingName=0x0)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclIOUtil.c:1825
#24 0x0000000004efc057 in Tcl_Main (argc=-1, argv=0x7fefffc78, appInitProc=0x4008f1 <Tcl_AppInit>)
    at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../generic/tclMain.c:441
#25 0x00000000004008ea in main (argc=2, argv=0x7fefffc68) at /usr/local/tcl/8.5.1-dbg/src/tcl/unix/../unix/tclAppInit.c:87
(gdb)
User Comments: dkf added on 2008-05-12 19:48:59:
Logged In: YES 
user_id=79902
Originator: NO

Finally managed to reproduce this on one of my development machines under an environment where I could see what was going wrong. Turned out to be a simple matter of needing to change how classes are unstitched from mixin classes. Fixed.

v_f added on 2008-05-02 21:00:23:

File Added - 276593: valgrind-8.6a0-20080502-x86_32-dbg.log

Logged In: YES 
user_id=1923679
Originator: YES

Tried again with HEAD version on 32-bit and 64-bit. It still fails at the same spot:

==16127== Invalid read of size 4
==16127==    at 0x46E37A8: ReleaseClassContents (tclOO.c:602)

0x046e37a8 in ReleaseClassContents (interp=0x42e3140, oPtr=0x5151358) at ./generic/tclOO.c:602
602             if (!(list[i]->flags & OBJECT_DELETED) && interp != NULL) {
(gdb) p list
$1 = (Class **) 0x5153b00
(gdb) p i
$2 = 0
(gdb) p list[i]
$3 = (Class *) 0x5153300
(gdb) p *list[i]
$4 = {thisPtr = 0x5152a08, flags = 1, superclasses = {num = 0, list = 0x5153418}, subclasses = {num = 0, size = 0, list = 0x0}, 
  instances = {num = 0, size = 0, list = 0x0}, filters = {num = 0, list = 0x0}, mixins = {num = 0, list = 0x5153ac8}, mixinSubs = {
    num = 0, size = 0, list = 0x0}, classHierarchy = {num = 0, list = 0x51571e8}, classHierarchyEpoch = 78, classMethods = {
    buckets = 0x5153354, staticBuckets = {0x0, 0x0, 0x0, 0x0}, numBuckets = 4, numEntries = 0, rebuildSize = 12, downShift = 28, 
    mask = 3, keyType = -1, findProc = 0x40bea2f <BogusFind>, createProc = 0x40bea64 <BogusCreate>, typePtr = 0x4149ca0}, 
  constructorPtr = 0x0, destructorPtr = 0x0, metadataPtr = 0x0}

File Added: valgrind-8.6a0-20080502-x86_32-dbg.log

dkf added on 2008-05-02 06:35:26:
Logged In: YES 
user_id=79902
Originator: NO

BTW, if you want to run the supposedly crashing test, use:
  make test TESTFLAGS="-constraints knownBug"

dkf added on 2008-05-02 06:32:10:
Logged In: YES 
user_id=79902
Originator: NO

Can't reproduce with HEAD of TclOO run against HEAD of Tcl (full debug build of both, on 32-bit x86 Linux with gcc toolchain). No idea what's changed...

v_f added on 2008-03-08 21:31:36:
Logged In: YES 
user_id=1923679
Originator: YES

There is another test script "oodestroy"
attached, which shows quite consistent behavior
independent of 32/64 bit arch and
debug/optimized build. The script does NOT raise a
segfault, but valgrind still reports illegal
reads and memory leaks.

Environment for x86_32:
Gentoo 2007.0, gcc-4.1.2, glibc-2.6.1
CFLAGS_DEBUG="-g -DPURIFY"
CFLAGS_OPTIMIZE="-O2 -march=athlon-xp -mfpmath=sse -fomit-frame-pointer"

Environment for x86_64:
Gentoo 2007.0, gcc-4.1.2, glibc-2.6.1
CFLAGS_DEBUG="-g -DPURIFY"
CFLAGS_OPTIMIZE="-O2 -march=athlon64 -mfpmath=sse -fomit-frame-pointer"

Tcl and TclOO configuration:
debug: ./configure --enable-shared --enable-symbols --disable-threads --disable-xft --srcdir=/usr/local/tcl/8.5.1-dbg/src/tcl/unix --prefix=/usr/local/tcl/8.5.1-dbg
opt: ./configure --enable-shared --disable-symbols --disable-threads --disable-xft --srcdir=/usr/local/tcl/8.5.1/src/tcl/unix --prefix=/usr/local/tcl/8.5.1

See attached valgrind reports for all four
cases. Hope this helps.

v_f added on 2008-03-08 21:30:28:

File Added - 269557: valgrind-x86_64-opt.log

Logged In: YES 
user_id=1923679
Originator: YES

File Added: valgrind-x86_64-opt.log

v_f added on 2008-03-08 21:29:56:

File Added - 269556: valgrind-x86_64-dbg.log

Logged In: YES 
user_id=1923679
Originator: YES

File Added: valgrind-x86_64-dbg.log

v_f added on 2008-03-08 21:29:22:

File Added - 269555: valgrind-x86_32-opt.log

Logged In: YES 
user_id=1923679
Originator: YES

File Added: valgrind-x86_32-opt.log

v_f added on 2008-03-08 21:28:44:

File Added - 269554: valgrind-x86_32-dbg.log

Logged In: YES 
user_id=1923679
Originator: YES

File Added: valgrind-x86_32-dbg.log

v_f added on 2008-03-08 21:27:21:

File Added - 269552: oodestroy

Logged In: YES 
user_id=1923679
Originator: YES

File Added: oodestroy

dkf added on 2008-03-06 20:46:09:
Logged In: YES 
user_id=79902
Originator: NO

I can reproduce this with 32-bit Linux as long as both Tcl and TclOO have symbols turned on. (Thanks to Miguel for testing this config for me.)

Attachments: