C_u*_*er5 2 c++ multithreading signals pthreads stdthread
1)我是std :: thread的新手,我想知道调用pthread_sigmask()
阻止在所创建的特定线程中的某些信号是否是一个好习惯std::thread
。
我不希望新线程接收SIGTERM,SIGHUP等信号,因为主进程已经安装了这些信号的处理程序。
因此,调用pthread_sigmask()
阻塞由创建的线程中的某些信号是一种好习惯std::thread
吗?
2)另外,我相信的效果pthread_sigmask(SIG_BLOCK, &mask, NULL)
仅适用于使用创建的线程
std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();
Run Code Online (Sandbox Code Playgroud)
并rotate_log()
作为启动函数调用。
并且的效果pthread_sigmask(SIG_BLOCK, &mask, NULL)
将不适用于std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach()
被调用的线程。
我的理解正确吗?
void rotate_log (std::string logfile, uint32_t max_files, bool compress)
{
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGTERM);
sigaddset (&mask, SIGHUP);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
// Do other stuff.
}
void Log::log (std::string message)
{
// Lock using mutex
std::lock_guard<std::mutex> lck(mtx);
_outputFile << message << std::endl;
_outputFile.flush();
_sequence_number++;
_curr_file_size = _outputFile.tellp();
if (_curr_file_size >= max_size) {
// Code to close the file stream, rename the file, and reopen
...
// Create an independent thread to compress the file since
// it takes some time to compress huge files.
if (!_log_compression_on)
{
std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();
}
}
}
Run Code Online (Sandbox Code Playgroud)
正确的方法是在创建线程之前在父级中设置所需的信号掩码,然后在父级中恢复它。这样,您新创建的线程从一开始就具有正确的信号掩码集。(信号掩码是从父线程继承的)。
当您在线程启动后设置信号掩码时,会有一段时间窗口,在此期间线程没有所需的掩码。
从理论上讲,std::thread
即使在具有POSIX线程的系统上,的实现也可能会创建非POSIX线程,并且pthread_sigmask
不适用于此类线程。(不过,Maxim Egorushkin的评论是正确的,您确实应该在创建线程的线程中阻塞线程,并仅取消阻塞要在新线程上处理的线程,以避免出现竞争情况。)
我不能说其他实现,但是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线程以外的任何东西的可能性很小。
归档时间: |
|
查看次数: |
309 次 |
最近记录: |