我需要为 Sendmail 开发一个 milter,并且考虑了很长时间我应该使用哪种语言/框架。最后,我决定直接使用 milter API 用纯 C 语言来完成。
我研究了 milter API 文档并认为我已经掌握了这些概念。但是有一件事情让我非常担心。从本节开始:
单个过滤器进程可以同时处理任意数量的连接。因此,所有过滤回调必须是可重入的,并使用一些适当的外部同步方法来访问全局数据 [...]。
虽然我非常理解为什么回调必须是线程安全的,但我不明白为什么它们必须是可重入的。我无法想象这些回调可以从中断或信号处理程序中调用(也许除了中止回调,我将不得不重新阅读这个)。
可重入要求的问题在于,可重入函数不能调用不可重入代码。因此,如果回调真的必须是可重入的,我就无法使用malloc()
其中的大多数其他库函数;来自man 3 malloc
:
为了避免多线程应用程序中的损坏,在内部使用互斥锁来保护这些函数使用的内存管理数据结构 [...]
这肯定意味着它malloc()
是线程安全的,它可能意味着它malloc()
不是可重入的,因此没有使用它的函数。
所以我有两个问题:
1) milter 回调是否真的需要重新进入,或者这实际上是 milter API 文档中“需要线程安全”的一个非常奇怪的措辞?
2)如果他们真的需要重入,我该如何规避上面提到的问题?由于 milter API 的特性,我很难想象如何在不使用malloc()
和其他不可重入库函数的情况下在回调中做一些合理的事情。