我需要为Sendmail开发一个milter并且已经考虑了很长时间我应该使用哪种语言/框架。最后,我决定直接使用milter API在普通C中完成它。
我研究过the milter API documentation并认为我已经掌握了这些概念。但是有一件事让我很担心。来自this section:
单个过滤器进程可以处理任意数量的连接 同时。因此,所有过滤回调必须是可重入的, 并使用一些适当的外部同步方法来访问 全球数据[...]。
虽然我很清楚为什么回调必须是线程安全的,但我无法理解为什么它们必须是可重入的。我无法想象那些回调可以从中断或信号处理程序调用(可能除了中止回调,我将不得不重新读取它)。
要求可重入的问题是重入函数不能调用不可重入的代码。因此,如果回调真的必须重入,我就不能在那里使用man 3 malloc
和大多数其他库函数;来自malloc()
:
为避免多线程应用程序中的损坏,使用互斥锁 内部保护所采用的内存管理数据结构 通过这些功能[...]
这肯定意味着malloc()
是线程安全的,这可能意味着malloc()
不是可重入的,因此没有使用它的函数。
所以我有两个问题:
1)milter回调是否真的需要重入,或者这实际上是milter API文档中“需要线程安全”的非常奇怪的措辞?
2)如果他们真的需要重新进入,我怎样才能规避上述问题?由于milter API的特性,我很难想象如何在不使用[Route("api/tickets")]
public HttpResponseMessage Post([FromBody]JObject newTicket)
{
var t = newTicket.ToObject<Ticket>();
TicketsRepository.InsertTicket(t);
HttpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
和其他非重入库函数的情况下在回调中做一些合理的事情。
答案 0 :(得分: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()
等。