2

我在尝试为每个线程创建一个 tcl 解释器时面临崩溃。我在 linux rh6 上使用 TCL 版本 8.5.9。每次它在不同的功能中崩溃似乎是某种内存损坏。通过网络似乎是一种有效的方法。有没有人遇到过类似的问题?多线程使用 Tcl 是否需要任何特殊支持?

这是以下导致 tcl 版本 8.5.9 崩溃的小程序。

#include <tcl.h>
#include <pthread.h>

void* run (void*)
{
        Tcl_Interp *interp =  Tcl_CreateInterp();
        sleep(1);
        Tcl_DeleteInterp(interp);
}

main ()
{
        pthread_t t1, t2;

        pthread_create(&t1, NULL, run, NULL);
        pthread_create(&t2, NULL, run, NULL);

        pthread_join (t1, NULL);
        pthread_join (t2, NULL);
}
4

2 回答 2

1

您需要使用启用线程的库构建。

在没有启用线程的情况下构建时,Tcl 内部在内存管理之类的地方使用了相当多的全局静态数据。它非常普遍。虽然最终有可能使事情正常进行(前提是您在单个线程中完成所有初始化和设置),但这将是相当不可取的。在你的情况下,事情以奇怪的方式崩溃一点也不奇怪。

当您使用启用线程的 Tcl 构建时,所有全局静态数据都将转换为线程特定数据或适当的互斥保护全局数据。然后允许同时从多个线程中使用 Tcl。但是,特定Tcl_Interp对象绑定到创建它的线程(因为它使用大量线程特定的数据)。就您而言,这没问题;您的解释器很高兴是每个线程的实体。

(好吧,前提是您还添加了一个初始化 Tcl 库本身的调用,这只需要完成一次。在创建任何这些线程之前放入其中。Tcl_FindExecutable(NULL);main()


由于向后兼容的原因,Tcl 8.5 默认在 Unix 上不启用线程——在 Windows 和 Mac OS X 上,由于它们处理低级事件的不同方式,它是启用线程的——但这在 8.6 中发生了变化。我不知道如何在 RH6 上获得启用线程的构建(除了自己从源代码构建它,这应该是直截了当的)。

于 2013-10-04T10:48:01.060 回答
1

默认的 Tcl 库未启用构建线程。(好吧,不是 8.5.9 afaik,而是 8.6)。

那么您是否检查过您的 tcl lib 是否已启用线程构建?

如果你有一个tclsh针对 lib 的构建,你可以简单地运行:

% parray ::tcl_platform
::tcl_platform(byteOrder)     = littleEndian
::tcl_platform(machine)       = intel
::tcl_platform(os)            = Windows NT
::tcl_platform(osVersion)     = 6.2
::tcl_platform(pathSeparator) = ;
::tcl_platform(platform)      = windows
::tcl_platform(pointerSize)   = 4
::tcl_platform(threaded)      = 1
::tcl_platform(wordSize)      = 4

如果::tcl_platform(threaded)为 0,则您的构建未启用线程。您需要通过传递--enable-threads给配置脚本来构建具有线程支持的版本。

您是否使用了正确的定义来声明您想要从 tcl.h 启用线程的宏?您应该添加-DTCL_THREADS 到编译器调用中,否则锁定宏将编译为无操作。

于 2013-10-03T19:19:10.140 回答