alloc:无效块 - Tcl_IncrRefCount 和 Tcl_DecrRefCount 对于线程 Tcl / 每个线程 1 个插值来说线程安全吗?

问题描述 投票:0回答:1

我们的 32 位服务器应用程序静态嵌入 tcl 8.4.11。在 Red Hat Linux 6.5 64 位上,我们遇到崩溃/核心转储。失败看起来像:

分配:无效块:0xf6f00f58:88 f6 0

在问题的底部,我记录了我们见过的两个不同的核心转储。

我们已经隔离了两个并发运行单独 TCL 解释器实例的线程之间共享的 TCL 对象的潜在根本原因。我们认为这是因为 TCL 对象从这些并发执行的 TCL 解释器传递到 Tcl_IncrRefCount / Tcl_DecrRefCount。

  1. 当 TCL 编译成线程时,Tcl_IncrRefCount / Tcl_DecrRefCount 线程安全吗?
  2. TCL 对象是否被 TCL 解释器实例共享?有没有办法禁用跨解释器实例的 TCL 对象共享?
  3. TCL 8.6.3 版本情况好一些了吗?
(gdb) bt
#0  __kernel_vsyscall () at arch/x86/vdso/vdso32/sysenter.S:49
#1  0x001b7871 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x001b914a in abort () at abort.c:92
#3  0x080f611c in Tcl_PanicVA ()
#4  0x080f613b in Tcl_Panic ()
#5  0x0810133c in Ptr2Block ()
#6  0x08100e04 in TclpFree ()
#7  0x080b46a7 in Tcl_Free ()
#8  0x08100686 in FreeStringInternalRep ()
#9  0x080fdac1 in ResetObjResult ()
#10 0x080fd316 in Tcl_GetStringResult ()
#11 0x0808aaad in run_tcl_proc (pDevice=0x8e0ba08, pInterp=0x8d798c0, iNumArgs=2, objv=0x115434c, bIsCommand=0 '\000', pCommand=0x0)
#12 0x08093672 in Tcl_begin_next_state (pDevice=0x8e0ba08, iNextState=RunPoll, pCommand=0x0)
#13 0x08093759 in Tcl_port_thread (dummy=0x8d1cab8)
#14 0x008bcb39 in start_thread (arg=0x1154b70) at pthread_create.c:301
#15 0x0026fc2e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:133
(gdb)
(gdb) bt
#0  __kernel_vsyscall () at arch/x86/vdso/vdso32/sysenter.S:49
#1  0x00395871 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x0039714a in abort () at abort.c:92
#3  0x080f611c in Tcl_PanicVA ()
#4  0x080f613b in Tcl_Panic ()
#5  0x0810133c in Ptr2Block ()
#6  0x08100e04 in TclpFree ()
#7  0x080b46a7 in Tcl_Free ()
#8  0x080d21b6 in TclExecuteByteCode ()
#9  0x080d1bc1 in TclCompEvalObj ()
#10 0x080fbd5c in TclObjInterpProc ()
#11 0x080b026a in TclEvalObjvInternal ()
#12 0x080d2716 in TclExecuteByteCode ()
#13 0x080d1bc1 in TclCompEvalObj ()
#14 0x080fbd5c in TclObjInterpProc ()
#15 0x080b026a in TclEvalObjvInternal ()
#16 0x080b0517 in Tcl_EvalObjv ()
#17 0x0808aa02 in run_tcl_proc (pDevice=0x94a2500, pInterp=0xac2bba0, iNumArgs=2, objv=0x11b034c, bIsCommand=0 '\000', pCommand=0x0)
#18 0x08093672 in Tcl_begin_next_state (pDevice=0x94a2500, iNextState=RunPoll, pCommand=0x0)
#19 0x08093759 in Tcl_port_thread (dummy=0x9365e98)
#20 0x00356b39 in start_thread (arg=0x11b0b70) at pthread_create.c:301
#21 0x0044dc2e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:133
(gdb)
c thread-safety tcl coredump panic
1个回答
0
投票

调用

Tcl_IncrRefCount
(实际上是一个简单的宏)和
Tcl_DecrRefCount
(一个复杂的宏)是线程安全的,但这只是因为每个
Tcl_Obj
只能从创建它的线程访问;对 T_IRC 和 T_DRC 的并行调用是可以的,只要它们具有不同的值即可。这样做的好处是访问不需要锁定(
Tcl_Obj
结构的内存管理器利用了这一点)。

请注意,除非您非常小心,否则多线程访问根本不是一个好的计划,因为如果需要应用类型转换,即使像

Tcl_GetIntFromObj
这样的读取器操作也可以写入底层结构。 这些操作没有被锁定。执行此操作需要非常深入地了解值的当前类型——通常不建议您首先在 Tcl 中考虑这些操作,尽管
tcl::unsupported::representation
可能会有所帮助在 8.6 中对此进行了探索——并且在线程之间进行了一些非常仔细的互锁,这样一个线程在另一个线程偷看时不会进行写入。 根本不要这样做,虽然不是 100% 准确,但却是最不可能导致头痛的方法。

您可能应该阅读更多有关如何做到这一点的内容。 ActiveState博客有合理的介绍。

© www.soinside.com 2019 - 2024. All rights reserved.