LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   How can a process detect the status of a signal (https://www.linuxquestions.org/questions/linux-newbie-8/how-can-a-process-detect-the-status-of-a-signal-614465/)

bluehive 01-18-2008 02:54 AM

How can a process detect the status of a signal
 
Hi all,
Is it possible for a process to know what signals it handle and the handler for each signal? I looked at signal API but couldn't find it helpful.

If I issue a command like this:
$ nohup ./my_exe&
- This process has a handler setup for SIGHUP.

But if it is invoked with 'nohup' like here, the process should _ignore_ its own handler and subsequently the signal. The reason is 'nohup' sets the handler for signal SIGHUP as 'SIG_IGN'.

And issuing '$kill -1 pid' should just be ignored!

So is it possible for a process to know the handler for a signal(like if its SIG_IGN or SIG_DFL). This way it can decide whether to catch it or not.

This program is in C.

Thanks,
Vishal

ashok449 01-18-2008 04:42 AM

Try this
Code:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch_signal(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
(void) signal(SIGHUP, SIG_IGN);
}
int main()
{
(void) signal(SIGHUP, ouch_signal);
while(1) {
printf("Hello World!\n");
sleep(1);
}
}

run the program and
#kill -HUP <pid>


Keep coding
-- Ashok Athukuri

osor 01-18-2008 03:41 PM

Quote:

Originally Posted by bluehive (Post 3026805)
Hi all,
Is it possible for a process to know what signals it handle and the handler for each signal? I looked at signal API but couldn't find it helpful.

It is possible for a process to examine the signal handler or action associated with a specific signal. This is done with sigaction().
Quote:

Originally Posted by bluehive (Post 3026805)
If I issue a command like this:
$ nohup ./my_exe&
- This process has a handler setup for SIGHUP.

But if it is invoked with 'nohup' like here, the process should _ignore_ its own handler and subsequently the signal.

This is wrong. I don’t think you understand nohup. When a process is started normally, all signal actions are set to SIG_DFL except those which were set to SIG_IGN in the parent process. So nohup will explicitly set the signal action for SIGHUP to SIG_IGN prior to the exec. This doesn’t in any way restrict your new process from overriding the signal action. In fact, if your program already changes the signal action, it should continue to do so (the only difference is that instead of changing it from SIG_DFL to a function address, it will change it from SIG_IGN to a function address).

Consider this demonstrative C code:
Code:

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

int main()
{
        struct sigaction oldsa;
        if(sigaction(SIGHUP, NULL, &oldsa) == -1) { /*mark*/
                perror("Getting signal action");
                exit(EXIT_FAILURE);
        }

        printf("This program was %scalled with nohup.\n",
              (oldsa.sa_handler == SIG_IGN ? "" : "not "));

        exit(EXIT_SUCCESS);
}

As it is, this function will currently figure out whether or not the program was invoked with nohup. If you wanted to, you could at the same time change the signal handler to your liking by changing the second argument of sigaction() in the line marked in the comment. You could also change the signal action to a custom signal handler anywhere subsequent the marked line (e.g., with signal()) if you wanted.

ashok449 01-18-2008 10:50 PM

Yeah, thats true if you wanna check the current status of the signal handler and then looking for action then do like

Code:

struct sigaction oldsa;
        if(sigaction(SIGHUP, NULL, &oldsa) == -1) { /*mark*/
                perror("Getting signal action");
                exit(EXIT_FAILURE);
        }
if (oldsa.sa_handler == SIG_DFL)   
  oldsa.sa_handler = SIG_IGN; 
     
  if (sigaction(SIGHUP, &oldsa, NULL) == -1)
      perror("Failed to ignore SIGHUP");


I guess that leaves you both chances to do that ...



-- Ashok Athukuri

bluehive 01-22-2008 04:55 AM

Hi "osor" and Ashok,
Thanks so much for the help and sharing the more about signals. I mistakenly skipped sigaction()'s functionality to gather info of "previous" handler. Thanks!
I could solve the issue but still nohup leaves some doubts to me. How does nohup changes signal handler for other process? As nohup should be forking the application, and changing handler for its child(But how because as far as I know signal handler info is kept in uarea? And it should be accessible to kernel or to the invoked process only)!

Thanks in advance,
Vishal

osor 01-22-2008 12:23 PM

Quote:

Originally Posted by bluehive (Post 3031162)
How does nohup changes signal handler for other process?

There are two different types of nohup one that’s builtin to some shells (which uses fork), and one that’s a stand-alone executable. Here’s how the standalone one works (I leave out any code relating to file descriptor juggling which is unrelated to your question):
Code:

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

int main(int argc, char *argv[])
{
        signal(SIGHUP, SIG_IGN);
        execvp(argv[1], argv+1);
       
        exit(EXIT_FAILURE);
}

Here’s what happens when you run something like:
Code:

nohup somecommand its arguments
  1. The shell forks off a process, and a new process with its own PID is created in the kernel’s process table.
  2. The image of the new process is replaced by executing nohup with the specific parameters.
  3. Now, in the new process image, the code tells the kernel that the process will ignore SIGHUPs.
  4. The process image is replaced by the file which was the first argument of the nohup command (“somecommand”) and the subsequent arguments are all the arguments after and including the first argument (“somecommand its arguments”).
Each time the process image was replaced, a bunch of things happen (e.g., file descriptors open in the calling process image shall remain open in the new process image, except for those whose close-on- exec flag FD_CLOEXEC is set), and you can see what these all are by reading the standard. One of these things is the way in which signal handling is inherited:
Quote:

Originally Posted by exec manpage
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see <signal.h>). If the SIGCHLD signal is set to be ignored by the calling process image, it is unspecified whether the SIGCHLD signal is set to be ignored or to the default action in the new process image. After a successful call to any of the exec functions, alternate signal stacks are not preserved and the SA_ONSTACK flag shall be cleared for all signals.



All times are GMT -5. The time now is 11:04 AM.