Providing/passing argument to signal handler

后端 未结 7 1143
夕颜
夕颜 2020-12-02 10:29

Can I provide/pass any arguments to signal handler?

/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */


        
相关标签:
7条回答
  • 2020-12-02 10:53

    Store the names of the files in a global variable and then access it from the handler. The signal handler callback will only be passed one argument: the ID for the actual signal that caused the problem (eg SIGINT, SIGTSTP)

    Edit 0: "There must be a rock solid reason for not allowing arguments to the handler." <-- There is an interrupt vector (basically, a set of jump addresses to routines for each possible signal). Given the way that the interrupt is triggered, based on the interrupt vector, a particular function is called. Unfortunately, it's not clear where the memory associated with the variable will be called, and depending on the interrupt that memory may actually be corrupted. There is a way to get around it, but then you can't leverage the existing int 0x80 assembly instruction (which some systems still use)

    0 讨论(0)
  • 2020-12-02 10:56

    This is a really old question but I think I can show you a nice trick that would have answered your problem. No need to use sigqueue or whatever.

    I also dislike the use of globals variables so I had to find a clever way, in my case, to send a void ptr (which you can later cast to whatever suits your need).

    Actually you can do this :

    signal(SIGWHATEVER, (void (*)(int))sighandler); // Yes it works ! Even with -Wall -Wextra -Werror using gcc
    

    Then your sighandler would look like this :

    int sighandler(const int signal, void *ptr) // Actually void can be replaced with anything you want , MAGIC !
    

    You might ask : How to get the *ptr then ?

    Here's how : At initialization

    signal(SIGWHATEVER, (void (*)(int))sighandler)
    sighandler(FAKE_SIGNAL, your_ptr);
    

    In your sighandler func :

    int sighandler(const int signal, void *ptr)
    {
      static my_struct saved = NULL;
    
      if (saved == NULL)
         saved = ptr;
      if (signal == SIGNALWHATEVER)
         // DO YOUR STUFF OR FREE YOUR PTR
       return (0);
    }
    
    0 讨论(0)
  • 2020-12-02 10:58

    You can use a signal handler which is a method of a class. Then that handler can access member data from that class. I'm not entirely sure what Python does under the covers here around the C signal() call, but it must be re-scoping data?

    I was amazed that this works, but it does. Run this and then kill the process from another terminal.

    import os, signal, time
    
    class someclass:
        def __init__(self):
            self.myvalue = "something initialized not globally defined"
            signal.signal(signal.SIGTERM, self.myHandler)
        def myHandler(self, s, f):
            # WTF u can do this?
            print "HEY I CAUGHT IT, AND CHECK THIS OUT", self.myvalue
    
    
    print "Making an object"
    a = someclass()
    
    while 1:
        print "sleeping.  Kill me now."
        time.sleep(60)
    
    0 讨论(0)
  • 2020-12-02 11:03

    I think you it's better to use SA_SIGINFO in sa_flags so the handler will get void signal_handler(int sig, siginfo_t *info, void *secret) in siginfo_t you can provide your params. Ty:HAPPY code

    0 讨论(0)
  • 2020-12-02 11:06

    A signal handler registration is already a global state equivalent to global variables. So it's no greater offense to use global variables to pass arguments to it. However, it's a huge mistake (almost certainly undefined behavior unless you're an expert!) to do anything from a signal handler anyway. If you instead just block signals and poll for them from your main program loop, you can avoid all these issues.

    0 讨论(0)
  • 2020-12-02 11:10

    You can't have data of your own passed to the signal handler as parameters. Instead you'll have to store your parameters in global variables. (And be really, really careful if you ever need to change those data after installing the the signal handler).

    Response to edit 0: Historical reasons. Signals are a really old and really low-level design. Basically you're just given the kernel a single address to some machine code and asking it to go to this specific address if such and such happens. We're back in the "portable assembler" mindset here, where the kernels provide a no-frills baseline service, and whatever the user process can reasonably be expected to to for itself, it must do itself.

    Also, the usual arguments against global variables don't really apply here. The signal handler itself is a global setting, so there is no relevant possibility of having several different sets of user-specified parameters for it around. (Well, actually it is not entirely global but only thread-global. But the threading API will include some mechanism for thread-local storage, which is just what you need in this case).

    0 讨论(0)
提交回复
热议问题