解决死锁时的奇怪行为

时间:2013-08-04 02:57:30

标签: c pthreads deadlock semaphore

几周前我上课了,我的解决方案很好,但是在观察一段时间后我注意到了一些奇怪的行为。 练习使用两个posix线程生成死锁,然后解决它。 (我抽象了解决方案,因此没有不必要的代码。

方案如下:

  • 我有两个共享两个虚构资源的主题
  • 两个线程按顺序启动,然后尝试占用两个资源(按顺序)
  • 两个主题的占用时间跨度不同
  • 当一个线程拥有两个资源时,他工作5秒然后释放资源并休息一下,当休息结束时,他再次尝试占用两个资源
  • 每隔8秒,一个函数检查两个线程是否都处于等待状态(两个线程都有一个资源并等待第二个)
  • 当发生死锁时,工作更多的线程将被取消然后重新启动

问题出在这里,取决于机器和编译标志,输出表示例如线程A被取消但线程B开始了。我在具有不同编译器的不同计算机上尝试了它,具有不同的istallations。 奇怪的是,我使用gcc -Wall -Werror -ansi -pedantic -D_POSIX_C_SOURCE=200809L -pthread -lrt进行编译,第二个死锁出现问题,但是当我删除-Wall和-Werror时,问题就出现了3.死锁0o

我上传了来源here。编译标志在源头,我尝试了gcc和clang。 我也尝试过Ubuntu 13.04和Arch。
Here是输出,我用“ - >”

标记了这些行

我忘记了什么,所以出现这种效果?我不认为某些库中存在错误。

1 个答案:

答案 0 :(得分:1)

问题是您将局部变量的地址传递给线程。并且当线程启动并且您正在取消引用使用来保存局部变量但现在拥有其他内容的地址位置时,此局部变量可能不再存在。

由于它位于程序的堆栈空间中,因此您不会遇到段错误。

以下是代码问题领域及其产生方式的重点:

void resolve_deadlock()
{
    void *pthread_exit_state;
    int id_a = THREAD_A;
    int id_b = THREAD_B;

   <some code to detect deadlocks and kill a thread>

 /* restart the killed thread */
 if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) {
                    perror("Create THREAD_B\n");
                    exit(EXIT_FAILURE);
            }
}

所以程序运行并且:

  1. 调用resolve_deadlock
  2. 线程X被杀
  3. 调用pthread_create来创建一个线程
  4. resolve_deadlock函数结束
  5. 堆栈在下一个函数调用上被覆盖
  6. 操作系统将我们打开并运行另一个线程
  7. 线程X运行并取消引用不再存在的本地var - &gt;未定义的行为。