【问题标题】:Deadlock inside malloc_atforkmalloc_atfork 内部的死锁
【发布时间】:2014-04-11 22:39:51
【问题描述】:

我的程序正在死锁,这里是死锁的前 4 帧:

#0  __lll_lock_wait_private () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:97
#1  0x00007f926250b7aa in _L_lock_12502 () at malloc.c:3507
#2  0x00007f926250a2df in malloc_atfork (sz=12, caller=<value optimized out>) at arena.c:217
#3  0x00007f926250881a in __libc_calloc (n=<value optimized out>, elem_size=<value optimized out>) at malloc.c:4040

我倾向于这是由我做错的事情引起的问题。当给服务器施加压力并将其提高到高使用水平时,我们会看到死锁,但否则我们无法重现这种情况。有谁知道这是什么错误造成的?

【问题讨论】:

  • malloc 是否有可能需要非常大的数字?(例如 3gb +)
  • @dheer: 你能显示死锁时所有线程的调用堆栈吗?从这个调用堆栈看来,这个线程正在等待某个被其他线程获取的锁。跨度>
  • 如果子进程不立即覆盖程序映像,通常不可能在多线程程序中使用fork()。典型的世界末日场景涉及一个多线程内存分配器,它会在分叉的进程中立即中断。
  • 在您的fork/clone 调用站点周围发布其他线程和代码的堆栈跟踪会很有帮助。
  • @KerrekSB:这应该是一个答案。

标签: c multithreading malloc fork


【解决方案1】:

根据 POSIX,在多线程进程中调用 fork 后,子进程处于异步信号上下文中,如果您在调用 _exit 之前执行任何其他操作而不是调用异步信号安全函数,则会调用未定义的行为。的exec 系列函数。

【讨论】:

  • 我的程序此时没有调用fork,它调用了calloc。程序在发送邮件的时候有一个fork,但是子进程只是dups,关闭文件描述符,调用execv,如果execv返回就退出。
  • 我刚刚重现了同样的问题,这次 malloc_atfork() 调用是在我的程序对 new 的调用中。在这两种情况下,或者在任何其他情况下,我实际上是在调用 fork()。
  • 您是否有一个最小的测试用例程序来重现该问题?如果是这样,我可以尝试一下,如果似乎存在真正的错误,我可以将错误报告给 glibc。
  • 另外,您是否有任何信号处理程序,您是否有可能从信号处理程序调用malloc(可能间接)?
【解决方案2】:

如果不同的执行线程以不同的顺序获取共享资源,您最常遇到死锁。在压力下出现是一个很好的指标。您的支持:

A == 1 2
B == 2 1

现在,假设您在 A 获取 1 之后但在它获取 2 之前获得了一个线程重新调度。线程B运行并获取2,然后控制权返回给A;它现在被阻塞在等待由 B 持有的资源 2,而 B 正在等待由 A 持有的资源 1。现在,A 不能继续,B 也不能;死锁。

死锁的另一个原因是对此的轻微变化,其中一个执行路径声明了一个资源而不遵守资源锁定;这会误导其他遵循规则的执行线程。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多