0

我需要为 Sendmail 开发一个 milter,并且考虑了很长时间我应该使用哪种语言/框架。最后,我决定直接使用 milter API 用纯 C 语言来完成。

我研究了 milter API 文档并认为我已经掌握了这些概念。但是有一件事情让我非常担心。从本节开始:

单个过滤器进程可以同时处理任意数量的连接。因此,所有过滤回调必须是可重入的,并使用一些适当的外部同步方法来访问全局数据 [...]。

虽然我非常理解为什么回调必须是线程安全的,但我不明白为什么它们必须是可重入的。我无法想象这些回调可以从中断或信号处理程序中调用(也许除了中止回调,我将不得不重新阅读这个)。

可重入要求的问题在于,可重入函数不能调用不可重入代码。因此,如果回调真的必须是可重入的,我就无法使用malloc()其中的大多数其他库函数;来自man 3 malloc

为了避免多线程应用程序中的损坏,在内部使用互斥锁来保护这些函数使用的内存管理数据结构 [...]

这肯定意味着它malloc()是线程安全的,它可能意味着它malloc()不是可重入的,因此没有使用它的函数。

所以我有两个问题:

1) milter 回调是否真的需要重新进入,或者这实际上是 milter API 文档中“需要线程安全”的一个非常奇怪的措辞?

2)如果他们真的需要重入,我该如何规避上面提到的问题?由于 milter API 的特性,我很难想象如何在不使用malloc()和其他不可重入库函数的情况下在回调中做一些合理的事情。

4

1 回答 1

0

在 Milter-API 的上下文中(它还强调它在内部使用 posix 线程),“可重入”函数被定义为可以安全地从多个线程同时执行的函数。这意味着不产生竞争条件。

术语“可重入”的这种用法与其他 UNIX/Linux API 文档一致,例如strtok

strtok_r()函数是strtok(). [..]

┌───────────┬───────────────┬───────────────────────┐
│Interface  │ Attribute     │ Value                 │
├───────────┼───────────────┼───────────────────────┤
│strtok()   │ Thread safety │ MT-Unsafe race:strtok │
├───────────┼───────────────┼───────────────────────┤
│strtok_r() │ Thread safety │ MT-Safe               │
└───────────┴───────────────┴───────────────────────┘

另请参阅其他功能,*_r()例如等。ctime_r()gmtime_r()

于 2021-06-27T15:41:52.783 回答