为什么malloc不是异步信号安全的?

19

为什么信号处理程序中不能使用 malloc?可能会发生什么错误?

1个回答

25

信号处理程序可以在任何时间被调用,甚至在另一个对malloc的调用正在进行时也可能发生。如果这种情况发生,会出现以下两种情况之一:

  1. 由于malloc无法获取堆锁定,您的进程将在信号处理程序中出现死锁。
  2. 由于malloc(或没有考虑到需要堆锁定)确实获取了锁,然后继续使堆不一致,导致稍后的崩溃,因此您的进程可能会损坏其堆。

1
有趣。但你能解释为什么这不能在正常的线程上下文切换期间发生吗?堆也是进程中所有线程共享的。除了信号处理程序调用外,malloc()不可抢占吗? - Amardeep AC9MF
10
这是一段老的内容,但它值得回答:当一个信号到达时,它会在进程内的线程中被处理。我能想到的最简单的情况是一个线程在调用malloc(假设在获得锁之后)时捕获了一个信号。然后,信号处理程序会调用malloc。当它试图获取锁时,它发现锁已经被持有,因此它会等待锁。原本将释放锁的线程部分将永远不会运行,因为它正在等待信号处理程序完成。信号处理程序将永远无法完成,因为它正在等待锁。 - J Teller
1
这就是死锁问题。当持有的锁是可重入的时,就会出现腐败问题。在这种情况下,信号处理程序能够获取锁(因为它由同一线程持有),并且在现有的malloc请求(在同一线程上)已经在进行中时,继续执行完全新的malloc请求,从而破坏堆。如果没有信号,其他线程使用锁来协调,这是不可能发生的。 - BeeOnRope
值得注意的是,实现允许以信号安全的方式实现malloc(),这样做将扩展程序从可能触发异步信号的各种条件中恢复的能力。声称malloc()不是信号安全的陈述并不意味着不应指定任何实现为信号安全,而是为了避免要求即使是那些客户不需要malloc()信号安全的实现,在运行此类安全性会很昂贵的平台上,也需要提供它才能符合规范。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接