Tcl_CreateInterp 怎么会陷入死循环呢?

How can Tcl_CreateInterp end up in an inifinite loop?

我正在使用 Tcl 库版本 8.6.4(使用 Visual Studio 2015,64 位编译)来解释来自 C/C++ 程序的一些 Tcl 命令。

我注意到如果我从不同的线程创建解释器,第二个会以无限循环结束:

#include "tcl.h"
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>

void runScript()
{
    Tcl_Interp* pInterp = Tcl_CreateInterp();

    std::string sTclPath = boost::filesystem::current_path().string() + "/../../stg/Debug/lib/tcl";
    const char* setvalue = Tcl_SetVar( pInterp, "tcl_library", sTclPath.c_str(), TCL_GLOBAL_ONLY );
    assert( setvalue != NULL );
    int i = Tcl_Init( pInterp );
    assert( i == TCL_OK );

    int nTclResult = Tcl_Eval( pInterp, "puts \"Hello\"" );
    assert( nTclResult == TCL_OK );

    Tcl_DeleteInterp( pInterp );
}

int main( int argc, char* argv[] )
{
    Tcl_FindExecutable(NULL);

    runScript();
    runScript();

    boost::thread thrd1( runScript );
    thrd1.join(); // works OK

    boost::thread thrd2( runScript );
    thrd2.join(); // never joins

    return 1;
}

这里是无限循环,在 Tcl 源代码中:

void
TclInitNotifier(void)
{
    ThreadSpecificData *tsdPtr;
    Tcl_ThreadId threadId = Tcl_GetCurrentThread();

    Tcl_MutexLock(&listLock);
    for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;
        tsdPtr = tsdPtr->nextPtr) {
    /* Empty loop body. */
    }
    // I never exit this loop because, after first thread was joined
    // at some point tsdPtr == tsdPtr->nextPtr

我做错了什么吗?是否缺少任何特殊函数调用?

注意:TCL_THREADS 在我编译 Tcl 时没有设置。但是,我觉得我在这里没有做错任何事。另外,添加

/* Empty loop body. */
if ( tsdPtr != NULL && tsdPtr->nextPtr == tsdPtr )
{
    tsdPtr = NULL;
    break;
}

循环内显然解决了这个问题。但是我对修改3rd party library源码不是很有信心...

向 Tcl 团队报告 bug 后,我被要求再次尝试使用启用 TCL_THREADS 编译的 Tcl 库。它解决了这个问题。

TCL_THREADS 被禁用是因为我使用在网上找到的 CMake Lists.txt 文件在 windows 上编译:这个文件实际上是为 Linux 编写的并且禁用了线程支持因为它无法在我的机器上找到 pthread。我最终使用 Tcl 团队提供的脚本编译了 Tcl 库:默认启用线程,无限循环消失了!