我正在编写一个必须处理信号的shell程序.我的相关信号处理相关代码如下:
#include <signal.h>
...
#include <sys/types.h>
...
void installSigactions( int, struct sigaction* );
void handler_function( int signal_id );
...
/*define signal table*/
struct sigaction signal_action;
/*insert handler function*/
signal_action.sa_handler = handler_function;
/*init the flags field*/
 signal_action.sa_flags = 0;
/*are no masked interrupts*/
sigemptyset( &signal_action.sa_mask );
/*install the signal_actions*/
sigaction( SIGINT, &signal_action, NULL );
编译给我以下警告和错误:
gcc -Wall -ggdb -ansi -static -pedantic -o os1shell2 os1shell2.c
os1shell2.c:35: warning: 'struct sigaction' declared inside parameter list
os1shell2.c:35: warning: its scope is only this definition or …我做了跟随信号处理程序
struct sigaction pipeIn;
pipeIn.sa_handler = updateServer;
sigemptyset(&pipeIn.sa_mask);
sa.sa_flags = SA_RESTART;
if(sigaction(SIGUSR1, &pipeIn, NULL) == -1){
    printf("We have a problem, sigaction is not working.\n");
    perror("\n");
    exit(1);    
}
如何删除或阻止此特定处理程序,以便我可以设置另一个使用相同信号的信号处理程序?谢谢.
根据C++17 标准 [support.signal],原子对象应满足以下要求才能在信号处理程序中使用:
\n\n\n\n
\n- [...], 或者\n
- \n
f是在对象上调用的非静态成员函数A,这样A.is_\xc2\xadlock_\xc2\xadfree()会产生true,或- \n
fA是一个非成员函数,并且对于传递给 的每个指向原子参数的指针f,atomic_\xc2\xadis_\xc2\xadlock_\xc2\xadfree(A)都会产生true。
std::atomic_flag正式地不适合这里(没有is_lock_free方法并且atomic_is_lock_free不能用std::atomic_flag对象调用)。虽然直观上来说,它非常接近(它是原子的且无锁的)。这是否意味着std::atomic_flag不能在信号处理程序中使用,或者它只是一个需要澄清的 C++ 标准?
据说你应该只在信号处理程序中调用异步安全函数.我的问题是,什么构成异步安全?我认为一个可重入且线程安全的函数是异步安全的吗?或没有?
在我的多线程GUI应用程序中,我有以下信号处理代码.我想改进这个代码,以便它是正确的和线程安全的但是在信号处理中有一些我不完全理解的东西:
void signal_handler(int sig)
{
        switch (sig)
        {
        case SIGTERM:
            ::wxLogMessage(wxT("SIGTERM signal received ..."));
            break;
        case SIGINT:
            ::wxLogMessage(wxT("SIGINT signal received ..."));
            break;
        case SIGUSR1:
            ::wxLogMessage(wxT("SIGUSR1 signal received ..."));
            break;
        default:
            ::wxLogMessage(wxT("Unknown signal received ..."));
        }
        // send wxCloseEvent to main application window
        ::wxGetApp().GetTopWindow()->Close(true);
}
我在init函数中注册信号处理程序:
// register signal handlers
signal(SIGTERM, signal_handler);
signal(SIGINT,  signal_handler);
signal(SIGUSR1, signal_handler);
我有这个装饰:
def timed_out(timeout):
    def decorate(f):
        if not hasattr(signal, "SIGALRM"):
            return f
        def handler(signum, frame):
            raise TimedOutExc()
        @functools.wraps(f)
        def new_f(*args, **kwargs):
            old = signal.signal(signal.SIGALRM, handler)
            signal.alarm(timeout)
            try:
                result = f(*args, **kwargs)
            finally:
                signal.signal(signal.SIGALRM, old)
            signal.alarm(0)
            return result
        new_f.func_name = f.func_name
        return new_f
    return decorate
但代码只能在linux上执行任何操作,因为在Windows上,没有SIGALRM.在Windows中使用此代码的最简单方法是什么?
所以我有一个库(不是我写的),不幸的是它abort()用来处理某些错误.在应用程序级别,这些错误是可恢复的,所以我想处理它们而不是用户看到崩溃.所以我最终编写这样的代码:
static jmp_buf abort_buffer;
static void abort_handler(int) {
    longjmp(abort_buffer, 1); // perhaps siglongjmp if available..
}
int function(int x, int y) {
    struct sigaction new_sa;
    struct sigaction old_sa;
    sigemptyset(&new_sa.sa_mask);
    new_sa.sa_handler = abort_handler;
    sigaction(SIGABRT, &new_sa, &old_sa);
    if(setjmp(abort_buffer)) {
        sigaction(SIGABRT, &old_sa, 0);
        return -1
    }
    // attempt to do some work here
    int result = f(x, y); // may call abort!
    sigaction(SIGABRT, &old_sa, 0);
    return result;
}
代码不是很优雅.由于这种模式最终必须在代码的几个点重复,我想简化一点,并可能将它包装在一个可重用的对象中.我的第一次尝试涉及使用RAII来处理信号处理程序的设置/拆除(需要完成,因为每个函数需要不同的错误处理).所以我想出了这个:
template <int N>
struct signal_guard {
    signal_guard(void (*f)(int)) {
        sigemptyset(&new_sa.sa_mask);
        new_sa.sa_handler = …我安装了python-daemon,现在我正在尝试正确处理信号.我的代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import signal, time, syslog
import daemon
def runDaemon():
    context = daemon.DaemonContext()
    context.signal_map = { signal.SIGTERM: programCleanup }
    context.open()
    with context:
        doMainProgram()
def doMainProgram():
    while True:
        syslog.syslog("pythonDaemon is running")
        time.sleep(5)
def programCleanup():
    syslog.syslog("pythonDaemon STOP")
if __name__ == "__main__":
    runDaemon()
当我启动代码时,一切都按预期工作:正在运行的文本pythonDaemon/var/log/syslog每5秒写一次.但是当我想终止守护进程时kill -TERM *PID*守护进程被终止但是syslog中缺少文本pythonDaemon STOP.
我究竟做错了什么?
注意:我没有在from daemon import runner这里工作,因为这给了我一个错误(看起来我需要一个旧版本lockfile),我不会解决这个问题,除非它是唯一能够正确处理信号的可能性.
我正在编写一个框架来实现在模拟器和未修改的主机软件中运行的RTL的协同仿真.编写主机软件以控制实际硬件,通常以两种方式之一工作:
前一种情况非常简单 - 编写一个库,它实现与驱动程序相同的读/写调用,并在运行模拟时与之相关联.这一切都非常有效,我可以运行未经修改的生产软件作为我的RTL模拟的刺激.
第二种情况比第一种情况要困难得多......
最初我以为我可以LD_PRELOAD用来拦截mmap调用.在我的实现中,mmap我会分配一些页面对齐的内存,然后mprotect设置一个信号处理程序来捕获SIGSEGV.
这种方法存在许多问题:
读取与写入
我可以确定访问的地址,siginfo_t->si_addr但不能确定访问是读还是写.
捕获重复访问
在信号处理程序中,我需要取消保护内存区域,否则SIGSEGV只要我的处理程序退出并且主机代码永远不会继续,我就会重复.但是,如果我取消保护区域,那么我的信号处理程序将不会捕获后续访问.
信号处理程序的肮脏
在模拟器驱动RTL并返回结果时阻塞信号处理程序违反了各种编程规则 - 特别是假设模拟器可以触发各种其他事件并在从此访问返回结果之前执行任意代码.
我想知道是否可以创建一个类似文件的对象,其行为类似于磁盘,而不是mprotect在缓冲区上使用.我没有找到任何表明这是可行的信息.
是否可以捕获对mmap区域的所有访问以及如何?
假设LD_PRELOAD并且mprotect是最佳路线:
mprotect该区域?在我的机器上,我有一个aarch64二进制文件,它是静态编译的.我使用带-g 6566标志的qemu-aarch64-static运行它.在另一个终端,我启动gdb-multiarch并连接为target remote localhost:6566.
我希望二进制文件引发一个信号,我在二进制文件中定义了一个处理程序.我gdb-multiarch在连接到远程后从内部设置了一个断点.但是,当信号出现时,断点不会在gdb-multiarch上命中.相反,在运行二进制文件的终端上,我得到一条消息:
[1]     + 8388 suspended (signal)  qemu-aarch64-static -g 6566 ./testbinary
为什么会这样?如何在处理程序上设置断点并对其进行调试?我尝试过SIGCHLD和SIGFPE.
signal-handling ×10
c ×5
linux ×5
c++ ×3
signals ×3
python ×2
system-calls ×2
alarm ×1
asynchronous ×1
atomic ×1
c++17 ×1
gdb ×1
longjmp ×1
mmap ×1
posix ×1
python-2.7 ×1
qemu ×1
raii ×1
windows ×1