在 std::thread 创建的线程中调用 pthread_sigmask 是一个好习惯吗? [英] Is it a good practice to call pthread_sigmask in a thread created by std::thread?

查看:57
本文介绍了在 std::thread 创建的线程中调用 pthread_sigmask 是一个好习惯吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1) 我是 std::thread 的新手,我想知道调用 pthread_sigmask() 以阻止特定 中的某些信号是否是一个好习惯strong> 由 std::thread 创建的线程.

1) I'm new to std::thread and I would like to know whether it is a good practice to call pthread_sigmask() to block some signals in a particular thread created by std::thread.

我不希望新线程接收SIGTERM、SIGHUP等信号,因为主进程已经为这些信号安装了处理程序.

I don't want the new thread to receive signals such as SIGTERM, SIGHUP, etc., because the main process has already installed handlers for these signals.

那么,调用 pthread_sigmask() 来阻塞由 std::thread 创建的线程中的一些信号是一个好习惯吗?

So, is it a good practice to call pthread_sigmask() to block some signals in a thread created by std::thread?

2) 另外,我相信 pthread_sigmask(SIG_BLOCK, &mask, NULL) 的效果只适用于使用

2) Also, I believe the effect of pthread_sigmask(SIG_BLOCK, &mask, NULL) will only apply to the thread created using

std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach();

并调用 rotate_log() 作为启动函数.

and calling rotate_log() as the start function.

pthread_sigmask(SIG_BLOCK, &mask, NULL) 的效果将不适用于 std::thread(&Log::r​​otate_log, this, _logfile,_max_files, _compress).detach() 被调用.

And the effect of pthread_sigmask(SIG_BLOCK, &mask, NULL) will not apply to the thread where std::thread(&Log::rotate_log, this, _logfile, _max_files, _compress).detach() is called.

我的理解正确吗?

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();
            }
        }
    }

推荐答案

理论上,std::thread 的实现可能会创建一个非 POSIX 线程,即使是在一个系统上具有 POSIX 线程,并且 pthread_sigmask 不适用于此类线程.(Maxim Egorushkin 的评论是正确的,不过——你真的应该在线程创建线程中阻塞信号,并且只解除你想要的阻塞在新线程上处理,以避免竞争条件.)

In theory, it is possible that an implementation of std::thread will create a non-POSIX thread even on a system which has POSIX threads, and pthread_sigmask would not work for such threads. (Maxim Egorushkin's comment is correct, though—you really should block signals in the thread-creating thread and only unblock those you want handled on the new thread, to avoid race conditions.)

我不能说其他实现,但是对于 GNU/Linux 实现来说,这种事情不太可能发生.当然,我也不能对这个实现发表权威性的评论,但是有太多的 C 和 C++ 代码假设用户空间线程(无论是 C、C++ 还是 POSIX)和内核任务(那些有 TID).十年前,人们仍然认为 n:m 线程库是可能的(其中 POSIX 线程的早期 1:m 实现只是一个特例).

I cannot speak for other implementations, but it it is extremely unlikely that such a thing will happen for the GNU/Linux implementation. I cannot speak authoritatively for this implementation either, of course, but there is simply too much C and C++ code out there that assumes a 1:1 mapping between userspace threads (whether C, C++, or POSIX) and kernel tasks (those things that have TIDs). Ten years ago, people still argued that an n:m threading library would be a possibility (of which the early 1:m implementations of POSIX threads were just a special case).

但是今天,程序员从一个线程调用 unshare (CLONE_FS) 来为该线程提供一个私有的当前目录,与所有其他线程分开.他们调用 setfscreatecon 并期望这只会影响调用线程.他们甚至直接调用系统调用 setresuidsetresgid 因为他们想避免 glibc 用来将更改传播到所有线程的 setxid 广播(内核不支持的东西)直接地).所有这些都将在 n:m 线程模型下停止工作.所以 std::thread 和 POSIX 线程必须映射到内核任务,强制执行 1:1 模型.

But today, programmers call unshare (CLONE_FS) from a thread to give that thread a private current directory, separate from all the other threads. They call setfscreatecon and expect that this only affects the calling thread. They even call the system calls setresuid and setresgid directly because they want to avoid the setxid broadcast that glibc uses to propagate the change to all threads (something that the kernel does not support directly). All this would stop working under an n:m threading model. So std::thread and POSIX threads would have to map to kernel tasks, enforcing the 1:1 model.

此外,C 和 C++ 都只有一个 GNU TLS ABI,这反过来又要求系统中只能有一种类型的线程,一个线程指针用于最终到达线程- 本地数据.

In addition, there is just one GNU TLS ABI for both C and C++, and that in turn pretty much requires that there can only be one type of thread in the system, with one thread pointer that is used to eventually reach thread-local data.

这就是为什么在 GNU/Linux 上,std::thread 不太可能使用 glibc 提供的 POSIX 线程以外的任何东西.

That's why it's so unlikely that on GNU/Linux, std::thread will ever use anything but the POSIX threads provided by glibc.

这篇关于在 std::thread 创建的线程中调用 pthread_sigmask 是一个好习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆