sigaction : using “void (*sa_sigaction)(int, siginfo_t *, void *);”

筅森魡賤 提交于 2021-01-28 10:01:18

问题


In sigaction manpage it's written :

sa_sigaction also specifies the action to be associated with signum. This function receives the signal number as its first argument, a pointer to a siginfo_t as its second argument and a pointer to a ucon- text_t (cast to void*) as its third argument.

So we can pass arguments to the signal handler (throught void*), but I can't find the way. Is there no way to put it anywhere?

Example :

struct ping_val
{
    int data1;
    int data2;
};

void ping(int sig, siginfo_t *siginf, void *ptr) 
{
    // ....
}

int main()
{
    struct sigaction sa_ping;
    ping_val foo;
    foo.data1 = 3;
    foo.data2 = 4;
    sa_ping.sa_sigaction = ping;
    sigemptyset(&sa_ping.sa_mask);
    sa_ping.sa_flags = 0;
    sigaction(SIGALRM, &sa_ping, NULL);
    // ....
}

Where I can pass foo structure value in argument in ping (with a cast in struct *)???


回答1:


You cannot pass any arguments to a signal handler because you never call it yourselves. A signal handler is called by the OS that doesn't know anything about your arguments.

The standard way to have a signal handler communicate with the main program is through global (or file-scoped) variables.




回答2:


The siginfo_t structure that a signal handler receives contains a union sigval si_value member:

union sigval {
    int    sival_int; // Integer signal value 
    void  *sival_ptr; // Pointer signal value 
}

So if you're sending signals within a single process (or among forks, in some cases, I suppose), you can send a pointer to some data.

I know of two ways to send a sigval value to a signal handler:

If you use timer_create to create a timer, you pass it a sigevent struct, which contains a union sigval sigev_value member. By convention, user code will set sigev_value.sival_ptr to be the timer ID, so that the signal handler can distinguish among several timers if necessary, but you can set it to any void * value.

If you use sigqueue (as opposed to kill, raise, faults, etc.) to send the signals, you give it a union sigval as an argument.




回答3:


You write:

So we can pass arguments to the signal handler [through the void* ucontext_t argument], but I can't find the way.

There is no such way to be found — the ucontext_t argument is set by the system itself and refers to "the receiving thread's context that was interrupted when the signal was delivered."

(Specifically, by spec it contains at least a reference to that interrupted context, and to a machine-specific representation of that context, and also the current context's stack and its set of blocked signals.)

You probably don't need any of this. If you want your program to take some action and/or modify its state on receipt of a signal, you've a limited number of tactics that can be safely used in a signal handler (volatile sigatomic_t flags, self-pipes, platform-specific interfaces), but then your main loop can of course do whatever you want with the knowledge that SIGFOO was just received.



来源:https://stackoverflow.com/questions/44879718/sigaction-using-void-sa-sigactionint-siginfo-t-void

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!