标签: signal-handling

从信号处理程序唤醒线程

我理解唯一的事情,ISO/C++ 11中允许的信号处理程序是读取或写入一个无锁的原子变量或者volatile sig_atomic_t(我相信,POSIX有点更宽松,允许调用一堆系统函数).

我想知道,如果有任何办法,唤醒正在等待条件变量的线程.就像这样:

#include <mutex>
#include <atomic>
#include <condition_variable>


std::mutex mux;
std::condition_variable cv;

std::atomic_bool doWait{ true };

void signalHandler(int){
    doWait = false;
    cv.notify_one();
}

int main() {
    //register signal handler
    //Do some stuff

    {//wait until signal arrived
        std::unique_lock<std::mutex> ul(mux);
        cv.wait(ul, []{return !doWait; });
    }

    //Do some more stuff
}
Run Code Online (Sandbox Code Playgroud)

其中至少有两个问题:

  1. 我相信,我不允许打电话notify_one()给信号处理程序(如果我错了,请告诉我)
  2. 信号可以在检查doWait和线程进入休眠之间到达,因此它永远不会被唤醒(显然,我无法锁定signalHander中的互斥锁以避免这种情况).

到目前为止,我能看到的唯一解决方案是在doWait变量上实现忙等待(可能在每次迭代中休眠几毫秒),这让我觉得非常低效.

请注意,即使我上面的程序只有一个线程,我用多线程标记了我的问题,因为它是关于线程控制原语.如果标准c ++中没有解决方案,我愿意接受使用Linux/POSIX特定功能的解决方案.

c++ linux multithreading signals signal-handling

6
推荐指数
1
解决办法
2178
查看次数

有没有办法测试我是否在信号处理程序中?

我必须处理一个可以从大型项目中的各个地方调用的日志记录模块。我遇到的问题是,有时可能会从信号处理程序内执行的代码中调用该模块。通常,日志模块使用 localtime() 和 strftime() 包含时间数据,但当然这些调用不是异步信号安全的,如果从信号处理程序中调用,可能会导致死锁。有没有办法(在 GNU/Linux 系统上)判断我的代码当前是否在信号处理程序上下文中执行,除了例如让每个信号处理程序在处理时设置一个标志?我认为简化我们的信号处理程序会更好,但在这种情况下,我无法选择在哪里调用日志记录模块。

c signals signal-handling async-safe

5
推荐指数
1
解决办法
764
查看次数

C++ 异常和信号处理程序

我正在阅读Bjarne Stroustrup 的The Design and Evolution of C++。关于异常处理和异步信号,如下所述:

异常可以用来处理信号之类的事情吗?在大多数 C 环境中几乎可以肯定不是。问题是 C 使用了像 malloc 这样不可重入的函数。如果在 malloc 中间发生中断并导致异常,则无法阻止异常处理程序再次执行 malloc。

一个 C++ 实现,其中调用序列和整个运行时库是围绕可重入的要求设计的,这将使信号抛出异常成为可能

作者所说的“没有办法阻止异常处理程序再次执行malloc”是什么意思?使函数可重入如何使信号处理程序抛出异常成为可能?

c++ language-design exception signal-handling

5
推荐指数
1
解决办法
3100
查看次数

用select()从管道读取时捕获信号

使用带管道的select() - 这就是我正在做的事情,现在我需要抓住SIGTERM它.我该怎么做?select()返回错误(<0)时是否必须这样做?

c signals pipe signal-handling

5
推荐指数
1
解决办法
1万
查看次数

释放信号处理程序内的内存

我正在编写一个使用套接字的API.在API中,我为各种项目分配内存.我想确保关闭套接字并释放内存以防有诸如Ctrl-C之类的信号.在研究这个时,似乎free()不在安全功能列表(man 7信号)上,因此,我无法释放信号处理程序内的内存.我可以关闭套接字就好了.有没有想过如何释放记忆?提前谢谢您的时间.

c linux signals signal-handling

5
推荐指数
2
解决办法
2852
查看次数

为单个线程创建信号处理程序

我想知道是否sigaction会为调用线程或整个进程创建一个信号处理程序。如果它解除阻塞信号并为整个进程创建信号处理程序,那么我如何确保只有一个线程会使用该信号处理程序并让其他线程阻塞该信号。

就我而言,我希望单个线程在警报信号消失时调用信号处理程序,而其他线程则简单地阻止它。


void alarmSigHandler(int signo){

}

void* alarm_thread_start_routine(void *arg){

    // Perform some tasks

}


int main(){

    // Main thread start

    /* Unblock alarm signal */
    /* Assign signal handler for alarm signal */

    /* Launch alarm signal handler thread */

    /* Block alarm signal with pthread_sigmask */

    /* Do something */

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

http://vip.cs.utsa.edu/classes/cs3733f2013/notes/SignalsAndThreads.html

如果将信号发送到线程程序,则任何线程都可以处理该信号。

每个线程都会继承进程信号掩码,但每个线程都有自己的信号掩码,可以使用 pthread_sigmask 进行修改。

sigprocmask 不应在线程环境中使用,但可以在创建线程之前使用。

在多线程环境中处理信号的最简单方法是有一个专用于信号处理的线程。

涉及信号安全的问题可以使用sigwait来处理:

The main process blocks all signals before creating any threads.
No signal handlers are set …
Run Code Online (Sandbox Code Playgroud)

c unix posix signals signal-handling

5
推荐指数
1
解决办法
3870
查看次数

Python - 使用“导入信号”处理 CTRL+D

我目前可以通过以下方式处理CTRL+ C

def hand_inter(signum, frame):
    print 'hey, nice job.'

signal.signal(signal.SIGINT, hand_inter)
Run Code Online (Sandbox Code Playgroud)

但是,我还需要处理CTRL+D但无法找到适合符号的“signal.CTRL+D”调用。

python signals exception interrupt signal-handling

5
推荐指数
1
解决办法
1万
查看次数

在 C 中获取键盘中断

程序:

#include<stdio.h>
void main()
{
    int time=1800;
    while(1){
        system("clear");
        time-=1;
        printf("%d\n",time);
        sleep(1);
    if(time==0)
        pause();
    }
}
Run Code Online (Sandbox Code Playgroud)

上述程序在时间达到 0 时停止。我的要求是在程序运行期间,如果我按下空格键或任何其他键等任何键,程序将暂停,再次按下该键,程序将恢复。因此,为此,在执行 while 条件之前,我们提交键盘中断的信号处理程序。在C中如何做到这一点。

获取键盘中断的函数是什么。我不想从用户那里得到输入,我想通过键盘处理用户产生的中断。

提前致谢..,

c unix linux keyboard signal-handling

5
推荐指数
1
解决办法
1万
查看次数

Linux中如何处理errno和signal handler?

当我们编写一个可能会改变errno的信号处理程序时,我们是否应该在信号处理程序的开头保存errno并在它的末尾恢复errno?就像下面一样:

void signal_handler(int signo){
    int temp_errno = errno;
    *** //code here may change the errno
    errno = temp_errno;
}
Run Code Online (Sandbox Code Playgroud)

linux signals signal-handling

5
推荐指数
1
解决办法
1126
查看次数

sigsuspend相当于原子系列的sigprocmask、pause、sigprocmask?

我正在阅读教科书关于 Linux x86-64 系统的信号/ECF 的章节(CS:APP,第 3 版,第 8 章,第 781 页),并发现了以下内容:

sigsuspend 函数暂时用 mask 替换当前的阻塞集,然后挂起进程,直到收到一个信号,该信号的操作是运行处理程序或终止进程。如果操作是终止,则进程将终止,而不从 sigsuspend 返回。如果操作是运行处理程序,则 sigsuspend 在处理程序返回后返回,将阻塞集恢复到调用 sigsuspend 时的状态。

sigsuspend 函数相当于以下函数的原子(不可中断)版本:

1       sigprocmask(SIG_BLOCK, &mask, &prev);
2       pause();
3       sigprocmask(SIG_SETMASK, &prev, NULL);
Run Code Online (Sandbox Code Playgroud)

据我了解,sigprocmask(SIG_BLOCK, &mask, &prev)应该导致阻塞集与掩码进行“或”运算,即将掩码中的信号添加到阻塞集中已有的信号中。但代码正上方的文本(以及我查找的 sigsuspend 的手册页)表示 sigsuspend“暂时用掩码替换当前的阻塞集”。对我来说,这听起来更像是sigprocmask(SIG_SETMASK, &mask, &prev),阻塞集设置为等于掩码中的信号。

那么为什么sigsuspend(&mask)等价于上面的代码(第 1-3 行)而不是下面的代码(第 4-6 行)呢?我对 signal.h 函数的直觉和/或理解哪里出了问题?

4       sigprocmask(SIG_SETMASK, &mask, &prev);
5       pause();
6       sigprocmask(SIG_SETMASK, &prev, NULL);
Run Code Online (Sandbox Code Playgroud)

如果我不清楚,让我问一个具体的问题(它可能会更好地解释我的直觉)。假设当前的阻塞集编码 SIGCHLD,而 sigset_t 掩码编码 SIGINT。我打电话sigsuspend(&mask)。无论哪种代码解释是正确的(第 1-3 行或第 4-6 行),在调用 sigsuspend 之后传递的 SIGINT …

c signals exception signal-handling multiple-processes

5
推荐指数
1
解决办法
468
查看次数