Tkinter崩溃(恐慌)呼叫Tcl_AppendFormatToObj

Tkinter崩溃(恐慌)呼叫Tcl_AppendFormatToObj,tkinter,tcl,panic,Tkinter,Tcl,Panic,我编写了一个Python应用程序,它使用Tkinter作为GUI。实际上,它有第二个用于TCP/IP通信的线程XMLRPC,允许labview连接并进行一些调用。这两个线程与一对线程安全队列通信。在运行了几天后,它崩溃了。我找不到完整的线索。到目前为止,我得到的最好结果是使用共享对象调用Tcl_AppendFormatToObj。显然,这来自以下Tcl函数: Tcl_AppendFormatToObj(..) { ... if (Tcl_IsShared(appendObj)) {

我编写了一个Python应用程序,它使用Tkinter作为GUI。实际上,它有第二个用于TCP/IP通信的线程XMLRPC,允许labview连接并进行一些调用。这两个线程与一对线程安全队列通信。在运行了几天后,它崩溃了。我找不到完整的线索。到目前为止,我得到的最好结果是使用共享对象调用Tcl_AppendFormatToObj。显然,这来自以下Tcl函数:

Tcl_AppendFormatToObj(..)
{
...
    if (Tcl_IsShared(appendObj)) {
    Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
    }
如果导致问题,请参阅有关格式化字符串的内容。有什么建议吗?我现在正在winpdb下运行Windows7上的脚本,等待并希望在恐慌再次发生时得到有用的跟踪

Tcl的Tcl_Obj值系统的语义——与Python不同,它没有值标识——要求值是可观察到的常量。在实践中,这意味着,如果存在单个引用(例如来自Tcl变量),则可以修改值,但如果存在多个引用,则可以修改两个变量、一个变量和一个参数等。除了使其类型发生变化外,不可以更改值,这一过程在Tcl术语中称为“闪烁”,因为类型并不意味着要成为Tcl中值的可观察方面,以防止“远处的幽灵”突变。这些规则由值变异函数强制执行,Tcl_AppendFormatToObj就是其中之一

为什么对一个正在变异的值有多个引用还不太清楚。我是根据你所说的来猜测的,一个线程正在变异这个值,而另一个线程正在使用这个值,在这段时间内它临时获取了第二个引用。在所有的语言中,种族条件都是丑陋的。在底层,修复方法通常是使用Tcl_DuplicateObj在变异线程中获取一个非共享副本,然后在进行更改后将其写入共享存储,但我怀疑这会破坏线程代码中其他地方的东西,您可能会在读卡器端假设引用没有更改

解决这个问题将是一件棘手的事情。Tcl解决这一问题的方法是停止尝试跨线程共享值,而是切换到消息传递,“writer”线程实际向“reader”线程发送消息以更新其状态。如果需要的话,这确实可以扩展到拥有多个读卡器,所以这并不都是坏事,并且可以在不全局锁定状态的情况下完成,这甚至更好。Tcl不需要像Python的全局解释器锁这样的东西,因为它首先通过线程对所有内容进行更强大的分区。我不知道如何将其转换为可以在Python中实现的东西…

Tcl的Tcl_Obj值系统的语义-与Python不同,它没有值标识-要求值是可观察到的常量。在实践中,这意味着,如果存在单个引用(例如来自Tcl变量),则可以修改值,但如果存在多个引用,则可以修改两个变量、一个变量和一个参数等。除了使其类型发生变化外,不可以更改值,这一过程在Tcl术语中称为“闪烁”,因为类型并不意味着要成为Tcl中值的可观察方面,以防止“远处的幽灵”突变。这些规则由值变异函数强制执行,Tcl_AppendFormatToObj就是其中之一

为什么对一个正在变异的值有多个引用还不太清楚。我是根据你所说的来猜测的,一个线程正在变异这个值,而另一个线程正在使用这个值,在这段时间内它临时获取了第二个引用。在所有的语言中,种族条件都是丑陋的。在底层,修复方法通常是使用Tcl_DuplicateObj在变异线程中获取一个非共享副本,然后在进行更改后将其写入共享存储,但我怀疑这会破坏线程代码中其他地方的东西,您可能会在读卡器端假设引用没有更改


解决这个问题将是一件棘手的事情。Tcl解决这一问题的方法是停止尝试跨线程共享值,而是切换到消息传递,“writer”线程实际向“reader”线程发送消息以更新其状态。如果需要的话,这确实可以扩展到拥有多个读卡器,所以这并不都是坏事,并且可以在不全局锁定状态的情况下完成,这甚至更好。Tcl不需要像Python的全局解释器锁这样的东西,因为它首先通过线程对所有内容进行更强大的分区。我不知道如何将其转换为可以在Python中实现的东西…

结果是其中一个队列不是线程安全的。Tk偶数队列不是线程安全的。因此,使用tk的root.after从另一个
读取,导致间歇性故障。相反,创建一个真正的队列,让非tk循环线程将一些东西塞进队列,并让tk线程中的代码监视队列的另一端。因此,在tk循环中,编写一个函数来清空真正的队列,并根据它发现的内容执行一些操作。使用after调用该函数本身。

结果表明其中一个队列不是线程安全的。Tk偶数队列不是线程安全的。因此,使用tk的root.after将来自另一个线程的内容放到tk的偶数队列中,会导致间歇性问题。相反,创建一个真正的队列,让非tk循环线程将一些东西塞进队列,并让tk线程中的代码监视队列的另一端。因此,在tk循环中,编写一个函数来清空真正的队列,并根据它发现的内容执行一些操作。当然,对于I/O密集型代码,Tcl程序首先通常是单线程的。Tcl在几乎所有描述的非阻塞I/O方面都非常出色,至少与您对nginx或node.js的预期一样好……当然,对于I/O密集型代码,Tcl程序首先通常是单线程的。Tcl在几乎所有描述的非阻塞I/O方面都非常出色,至少与您对nginx或node.js的预期一样好…