1)我是std :: thread的新手,我想知道调用UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
来阻止由创建的特定线程中的某些信号是否是一个好习惯pthread_sigmask()
。
我不希望新线程接收SIGTERM,SIGHUP等信号,因为主进程已经安装了这些信号的处理程序。
那么,调用std::thread
来阻止pthread_sigmask()
创建的线程中的某些信号是一种好习惯吗?
2)另外,我相信std::thread
的作用仅适用于使用
pthread_sigmask(SIG_BLOCK, &mask, NULL)
并调用std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();
作为启动函数。
rotate_log()
的作用不适用于调用pthread_sigmask(SIG_BLOCK, &mask, NULL)
的线程。
我的理解正确吗?
std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach()
答案 0 :(得分:4)
理论上,即使在具有POSIX线程的系统上,std::thread
的实现也可能会创建非POSIX线程,而pthread_sigmask
不适用于此类线程。 (不过,{Maxim Egorushkin's comment是正确的,您确实应该在创建线程的线程中阻塞线程,而仅取消阻塞要在新线程上处理的线程,以避免出现竞争情况。)
我不能代表其他实现,但是极端对于GNU / Linux实现来说不太可能发生。当然,我也不能对此实现进行权威性的讲授,但是那里有太多的C和C ++代码,它们假定用户空间线程(无论是C,C ++还是POSIX)和内核任务(那些有TID)。十年前,人们仍然认为n:m线程库是一种可能(其中早期的POSIX线程的1:m实现只是一个特例)。
但是,今天,程序员从线程中调用unshare (CLONE_FS)
,以给该线程一个私有的当前目录,该目录与所有其他线程分开。他们调用setfscreatecon
,并期望这只会影响调用线程。他们甚至直接调用系统调用setresuid
和setresgid
,因为他们想避免glibc用于将更改传播到所有线程的setxid广播(内核不直接支持的东西)。所有这些都将在n:m线程模型下停止工作。因此,std::thread
和POSIX线程将必须映射到内核任务,并执行1:1模型。
此外,对于C和C ++只有一个GNU TLS ABI,这反过来又非常需要系统中只有一种类型的线程,并且使用一个线程指针来最终到达线程-本地数据。
这就是为什么在GNU / Linux上,std::thread
除了glibc提供的POSIX线程之外几乎不会使用任何东西的原因。
答案 1 :(得分:2)
正确的方法是在创建线程之前先在父级中设置所需的信号掩码,然后在父级中还原它。这样,您新创建的线程从一开始就具有正确的信号掩码设置。 (信号掩码是从父线程继承的。)
在线程启动之后设置信号掩码 时,线程会在一段时间内没有所需的掩码。
答案 2 :(得分:1)
如果需要在POSIX系统上的多线程程序中设置信号掩码,那么pthread_sigmask
是您需要使用的功能。 C ++标准库中没有与信号掩码交互的功能。
此外,我相信
pthread_sigmask(SIG_BLOCK, &mask, NULL)
的作用仅适用于使用...创建的线程。
pthread_sigmask
适用于在其中执行调用的线程,而不管其创建方式如何。它不适用于其他任何现有线程。在您的示例中,在rotate_log
创建的线程中执行了调用pthread_sigmask
的函数std::thread
。