POSIX 是否保证信号不会传递到部分初始化的线程?
在 POSIX 线程的大多数实现中,新创建的线程需要进行一些初始化,然后才能处于能够运行应用程序代码的一致状态。这可能涉及解锁线程结构中的锁、初始化使用线程寄存器的实现中的“线程寄存器”、初始化线程本地数据(编译器级 TLS 或 POSIX 线程特定数据)等。我找不到明确的说明保证所有这些初始化将在线程接收任何信号之前完成;我能找到的最接近的是 2.4.3:
下表定义了一组异步信号安全的函数。因此,应用程序可以不受限制地从信号捕获函数调用它们:
...
大概,其中一些函数(至少 fork,它必须检查由 pthread_atfork 建立的全局状态) 函数)取决于线程是否处于一致的初始化状态。
困扰我的一件事是我已经阅读了很多 glibc/nptl 源代码,并且找不到任何显式同步来防止新创建的线程在完全初始化之前处理信号。我希望调用 pthread_create
的线程在调用 clone
之前阻止所有信号,并让新线程在初始化完成后取消阻止它们,但我找不到任何代码为此,我也没有在 strace 输出中看到它。
On most implementations of POSIX threads, some initialization is required in the newly-created thread before it is in a consistent state able to run application code. This may involve unlocking locks in the thread structure, initializing the "thread register" in implementations that use one, initializing thread-local data (either compiler-level TLS or POSIX thread-specific data), etc. I can't find a clear guarantee that all of this initialization will be finished before the thread can receive any signals; the closest I can find is in 2.4.3:
The following table defines a set of functions that shall be async-signal-safe. Therefore, applications can invoke them, without restriction, from signal-catching functions:
...
Presumably, some of these functions (at least fork
, which has to inspect global state established by the pthread_atfork
function) depend on the thread being in a consistent, initialized state.
One thing that bothers me is that I've read much of the glibc/nptl source, and cannot find any explicit synchronization to prevent a signal from being handled by the newly-created thread before it's fully initialized. I would expect the thread calling pthread_create
to block all signals before calling clone
, and for the new thread to unblock them once initialization is finished, but I can't find any code to that effect nor do I see it in strace
output.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
(我不认为这是一个真正的答案,但对于评论来说太大了)
这是一个非常有趣的问题。我查看了
pthread_create
的 glibc 代码来了解它的行为方式,除非我完全错过了一些东西,否则似乎没有任何特殊行为来阻止它(例如在 < code>clone 并在进行一些设置后在子级中解除阻塞(在记录线程创建时间并且设置了 C++ 捕获所有异常处理程序之后,这甚至在 C 代码中也会发生})。我期待找到一条评论提到这种情况的可能性,甚至可能提到 POSIX 说要做什么(或者提到它没有说要做什么)。
也许您应该始终将
pthread_create
包装在代码中以阻止和恢复信号,并通过取消阻止调用启动所有线程函数。这很可能是 pthreads(或 glibc 或我对代码的理解)中的一个过度站点。
(I don't think that this is a real answer, but it is to big for a comment)
This is a very interesting question. I've looked through glibc code for
pthread_create
to see how it behaves and unless I'm totally missing something there doesn't seem to be any special behavior to stop this (such as blocking all signals beforeclone
and unblocking them in the in the child after some setup {after recording the thread creation time and the C++ catch all exception handler is set up, which happens even in the C code} ).I was expecting to find a comment that mentioned the possibility of this situation and maybe even a mention of what POSIX said to do (or a mention that it did not say what to do).
Perhaps you should always wrap
pthread_create
in code to block and restore signals, and start all thread functions with an unblock call.This may very well be an over site in pthreads (or glibc or my understanding of the code).
POSIX
pthread_create
规范 要求我这样做理解:但我没有足够的经验来说明在各种实现中事情都是这样的。
The POSIX
pthread_create
specification mandates this from my understanding of:But I don't have enough experience to say that the things are this way in various implementations.
pthread_create 是一个阻塞调用。在调用之前没有(新)线程可以向其发送信号,并且有一个线程在调用之后向发送信号,因此该线程的 ID由调用返回。
因此,我得出结论,该线程当时必须有效并已初始化......
pthread_create is a blocking call. There is no (new) thread for it to send the signal to before the call, and there is a thread to send the signal to after the call, thus the thread's ID is returned by the call.
Therefore, I'd conclude that the thread has to be valid and initialized at that time...