【问题标题】:Why is this simple multithreaded program freezing in eclipse - mingw32/gdb?为什么这个简单的多线程程序在 eclipse - mingw32/gdb 中冻结?
【发布时间】:2012-06-24 20:17:45
【问题描述】:

下面的程序绝对随机地在 GDB 7.4(MinGW32、Eclipse、Windows)中保持挂起/冻结,估计大约每 5 或 6 次运行。通过在 Eclipse 中混合调试按钮,然后检查尚未终止的调试实例,最容易找到它。你当然可以像正常人一样运行它来做同样的事情,并且很快就会得到同样的结果。

未附加到 GDB 时,样本永远不会冻结。曾经。我也无法在 VC++ Express 下暴露同样的问题(这是一个不同的示例,但实际上只是相同的想法)。

它主要围绕线程创建、线程删除和程序终止。另外值得注意的是,即使 main 返回 -1 作为退出代码,当附加到 GDB 时,只要程序不冻结它就会以代码 0 退出。

另一个有趣的事实 - 当我取消注释“Sleep(1)”调用时,它会在 80% 的时间停止挂起。但是,当它确实冻结时,它会在打印“Return -1\n”后冻结。 所有其他终止继续返回 0(除了没有 gdb 运行时)。

废话不多说,代码:

#include <stdio.h>
#include <windows.h>
#include <process.h>

void __cdecl callback(void *arg)
{
    int count = 0;

    while(count < 10)
    {
        printf("Thread 2(%i): looping %i\n", (int)arg, count);
        count++;
    }

    printf("Ending thread...\n");
    _endthread();
}

int main(int argc, char *argv[])
{
    // Mingw32 on windows w/ eclipse - fix console output not showing up until the app terminates
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);

    bool runMain = true;

    int runCount = 0;

    while(runMain == true)
    {
        if(runCount == 5)
        {
            printf("Thread starting... ");
            int result = _beginthread(callback, 0, (void*)5);
//          Sleep(1);

            if(result == 0)
                printf("[FAILURE]\n");
            else
                printf("[SUCCESS]\n");
        }

        printf("Thread 1: %i\n", runCount);
        runCount++;

        if(runCount == 20)
            runMain = false;
    }

    printf("Return -1\n");
    return -1;
}

您认为是什么原因造成的,更重要的是 - 我该如何解决?

【问题讨论】:

  • 我很惊讶它能做什么。 main() 创建 20 个线程并退出,终止进程,可能在其他线程执行任何操作之前。 printf() 是线程安全的吗?退出 main() 是否会关闭标准输入/输出?
  • @MartinJames 感谢您查看,但您不正确。只有一个线程被创建 - 当 runCount 达到 5 时。并且该线程必须打印到控制台 10 次,而主线程必须执行 15 次调用才能打印到控制台。我使用这些变量无济于事,这是我遇到问题的超级简化版本。我将其分解为导致问题的最小代码。发布模式运行没有问题,两个线程都执行并且主线程不产生(printf 调用不交错)。
  • 有人可以至少测试一下吗?为什么马丁的评论被 1 点赞?他完全跑题了……
  • 您可以尝试在 main() 的末尾添加一些内容以使程序不会退出吗?即使做一些像请求输入这样简单的事情也能做到这一点。您在上面争辩说,在线程完成工作之前,主程序不可能退出——但让我们确保情况确实如此。
  • @BSchlinker 感谢您对此进行调查。最后暂停程序以让线程完成并不是真正的问题。问题是使用 GDB 调试时相当随机但一致的挂起。它会在不同的时间挂起——有时在线程开始时,有时在程序结束时。但请注意,这是我的问题的最简单版本 - 我真正的应用程序不会停止它不断循环并出现相同的症状。

标签: c multithreading gcc gdb mingw


【解决方案1】:

没有解决办法。 GDB #17247 相关的一个 bug。

向 gdb 或您的应用程序发送一个 SIGCONT 信号使其再次工作。

下次尝试运行此命令:

killall -s SIGCONT <gdb | your application process name>

kill -18 <gdb pid|application pid>

【讨论】:

  • 很好地找到了该问题报告,但“没有解决方案”是不必要的黯淡。您已经提出了一种将挂起变为暂停的替代方案。由于该问题似乎已在 gdb 中进行了修补,因此还有更新 gdb(至少到 v7.8)或从适当修补的源重新构建它的替代方法。
猜你喜欢
  • 2020-02-23
  • 2011-11-13
  • 2013-03-23
  • 2017-09-07
  • 2022-01-23
  • 2012-01-17
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
相关资源
最近更新 更多