UNIX/Linux signal handling: SIGEV_THREAD

15,660

Solution 1

struct sigevent is not about specifying how the process will handle a signal - struct sigaction and sigaction() are how you do that. Instead, struct sigevent is used to specify how your process will be informed of some asychronous event - like the completion of asychronous IO, or a timer expiring.

The sigev_notify field specifies how the event should be notified:

  • SIGEV_NONE - no notification at all. The remainder of the fields are ignored.
  • SIGEV_SIGNAL - a signal is sent to the process. The sigev_signo field specifies the signal, the sigev_value field contains supplementary data that is passed to the signal handling function, and the remainder of the fields are ignored.
  • SIGEV_THREAD - a function is called in a new thread. The sigev_notify_function field specifies the function that is called, sigev_value contains supplementary data that is passed to the function, and sigev_notify_attributes specifies thread attributes to use for the thread creation. The remainder of the fields are ignored.

Note in particular that if you set SIGEV_THREAD, the sigev_signo field is ignored - the struct sigevent is about specifying either a thread or a signal as a notification method, not about specifying a thread as the way that a signal should be handled.

The struct sigevent must also be passed to a function - like timer_create() - that sets up the asychronous event that will be notified. Simply creating a struct sigevent object does not do anything special.

If you wish to use a dedicated thread to handle a signal, create the thread up front and have it loop around, blocking on sigwaitinfo(). Use sigprocmask() to block the signal in every other thread.

Solution 2

I think you are mixing up your signal handling idioms here, you create a sigevent structure and then do nothing with it and then use signal() within the signal handler. The following code shows a very simple signal handling routine based on your code; note that I have changed the definition of my_handler. If you need more sophisticated handling then sigaction() is probably the system call you need to look into.

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

void my_handler(int sig)
{
 printf("my_handler caught\n");
 signal(sig,my_handler);
}

int main()
{
 signal(SIGRTMIN,my_handler);
 kill(0,SIGRTMIN); // This should invoke the signal and call the function
 while(1) ;  // Infinite loop in case the program ends before the signal gets caught!
}

This works under cygwin on my windows box (no access to a linux box at the minute).

Share:
15,660
RajSanpui
Author by

RajSanpui

Around 9+ years experience into development C, C++, and Linux domain. Also understand Core-Java and consider it as a secondary skill. Currently, in addition to the developer responsibilities, i am also serving the role of DevOps engineer.

Updated on June 05, 2022

Comments

  • RajSanpui
    RajSanpui almost 2 years

    I have put a simple signal handler in my code. I have initialised the sigevent structure, with a handler function to catch the signal.

    Can someone please pin-point as to why the code is not working? Ideally if there is a signal, my handler should be called. But it is not.

    Please help me, Thanks Kingsmasher1

    enter code here
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <signal.h>
    #include <time.h>
    
    void my_handler(int sival_int, void* sival_ptr)
    {
     printf("my_handler caught\n");
     signal(sig,my_handler);
    }
    
    int main()
    {
     struct sigevent sevp;
    
     sevp.sigev_notify=SIGEV_THREAD;
     sevp.sigev_signo=SIGRTMIN;
     sevp.sigev_value.sival_ptr=NULL;
     sevp.sigev_notify_function=(void*)my_handler;
     kill(0,SIGRTMIN); // This should invoke the signal and call the function
    }
    
  • Fred Foo
    Fred Foo about 13 years
    But the OP's not doing anything with the sigevent must logically be the problem, so +1.
  • RajSanpui
    RajSanpui about 13 years
    This methos i am aware of, but i want to use the sigevent and use the SIGEV_THREAD to invoke the function. If you can please help me in that way, it will be great
  • Jackson
    Jackson about 13 years
    From a brief trawl through the docs the problem that you've got is that sigevent is about event handling not about signal handling. It sounds like you want to invoke a signal handler in a new thread whenever the SIGRTMIN signal is received by your process while sigevent is used for things like async io (see the aio man pages). You need to look at the docs for signal() and if your OS supports it sigaction() to see what you can do.