Link to home
Start Free TrialLog in
Avatar of prashanthks
prashanthks

asked on

Signal handling in Unix

I have a test.cgi executable which has a link and then i have an infinite while loop.Now if i click on the link provided, the cgi receives a SIGTERM and then SIGPIPE.I have written handlers for these signals and i have not exited in these handlers.But still the test.cgi is terminating.Whether it received SIGKILL after this.If it receives SIGKILL how do I handle it? I dont want my test.cgi to be terminated by a signal.I want a normal termination for it.

Here is the code

#include<stdio.h>
#include<signal.h>
int flag=0;
void handlerterm() {
    system("echo \"SIGTERM\n\"  >> /home/prashantk/sigpipe.txt");
}
void handlerpipe() {
    system("echo \"SIGPIPE\n\"  >> /home/prashantk/sigpipe.txt");
    flag=1;
}
main() {
    long count = 0,pid =1;
    char counttemp[512];
    system("echo \" \"  > /home/prashantk/sigpipe.txt");
    signal(SIGTERM,handlerterm);
    signal(SIGPIPE,handlerpipe);
    printf("Content-type:text/html\n\n");
    printf("<HTML><HEAD><BODY>\n");
    printf("<a href=\"/cgi-bin/test1.cgi\">testlink</a>\n");
    while(1) {
        if(!flag)
            printf(" ");
    }
    printf("</BODY></HTML>\n");
}

Here First SIGTERM is received,then SIGPIPE is received.I handle both.But still the process get killed.
The program given above creates my test.cgi
Avatar of ufolk123
ufolk123

Can you provide some code here.There is a race condition in old Unix signal usage in which rapid delivery of signals results in to resetting of signal handler.also write What is your enviornment.
Also you can not handle SIGKILL.There seems to be no source of SIGKILL unless you send it yourself ( unix will never send it to your program internally )so problem is somewhere else
Avatar of prashanthks

ASKER

Edited text of question.
I think once the signal handler is invoked, the signal behaviour
becomes the default.

Try adding the code:
signal(SIGTERM,handlerterm);

to the end of handlerterm() and
  signal(SIGPIPE,handlerpipe);
to end of handlerpipe.

Also if you have truss in your machine. Run the program under
truss and find out what caused the program to exit.
OOPS I overlooked the code part.Yes as doubted by me earlier it is signal behaviour which is resetting the signal handler to default.Try using the
sigaction
if available on your computer.
To Meerak:
Adding the signal handler install code
signal(SIGTERM,handlerterm);

to the end of handlerterm() and
  signal(SIGPIPE,handlerpipe);
to end of handlerpipe.

will not work as there can be delivery of a signal between start and end of handlerterm().
Let us see if it helps prsanthks.
hi prashanthks ... where are you ?
I am sorry. I am busy with my work.I have not been able to check your suggestion .I will check it sooner and reply.
Hi ufolk,
      I am sorry for the delayed response.I tried out sigaction as told by you. But the behaviour is same.Ths signal is handle once. After that the process gets killed. In the struct sigaction I set the sa_handler to the function name i.e,
pipeact.sa_handler = handlerpipe; and
termact.sa_handler = handlerterm;
Then I made
pipeact.sa_flags = 0; and
termact.sa_flags = 0;
Then I called
sigaction(SIGPIPE,&pipeact,NULL);
sigaction(SIGTERM,&termact,NULL);

But still the thing seems not to be working.
On some systems ( specifically QNX etc) the system() function call also modifies the signal state of a program.You try to remove system from your handlers and instead keep the file desc open of sigpipe.txt and try to write the text using file i/o calls.


void handlerterm() {
    system("echo \"SIGTERM\n\"  >> /home/prashantk/sigpipe.txt");
}

as

void handlerterm() {
    fputs(fd,"SIGTERM\n\" );
}

where fd=fopen of /home/prashantk/sigpipe.txt in main code.



It is not working out ufolk. I tried commenting out the "system" system call in both the handlers.
Hello,

The problem is that you dont let signals comming in.

you need to use pause() somewhere.

I modified your version and i use pause() and it worked well.

If you want to do processing in the same time then use pause() and alarm() with an action for alarm.

I hope this helps.
Hi again, watch-out, on some systems (unix),
the system function can block signals also.
This can create loops ! and loops and loops and ...
Hi again, again,

your:

int flag=0;

watch out, you should use and atomic version of it.

ex:

sig_atomic_t flag=0; this will ensure that only one guy (child) will update at one time.
you dont have any childs in your example but this is a good practice.

;-)
ASKER CERTIFIED SOLUTION
Avatar of fredos
fredos

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi fredos could you please send your version of code so that I can know where to put the pause.
I tried with pause and alarm.But it did not work.Could you please send me the code.
yes sure tonight !
OK this is the basic of it, once you get a signal
it will be executed (the handler), but if you want to do something in the same time, use threads/fork or same task with alarm (in seconds) or there is a fine one in milliseconds (see ginfo libc there is also an example)

hope this helps

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

int flag=0;

void handlerterm() {
    printf("in the term handler\n");
    system("echo \"SIGTERM\n\"  >> ./sigpipe.txt");
}

void handlerpipe() {
    printf("in the pipe handler\n");
    system("echo \"SIGPIPE\n\"  >> ./sigpipe.txt");
    flag=1;
}

main()
{
    long count = 0,pid =1;
    char counttemp[512];
    system("echo \" \"  > ./sigpipe.txt");

    signal(SIGTERM,handlerterm);
    signal(SIGPIPE,handlerpipe);

    printf("Content-type:text/html\n\n");
    printf("<HTML><HEAD><BODY>\n");
    printf("<a href=\"/cgi-bin/test1.cgi\">testlink</a>\n");

    pause();

    printf("</BODY></HTML>\n");
}