Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > <signal.h> - question about signals

Reply
Thread Tools

<signal.h> - question about signals

 
 
Jackie
Guest
Posts: n/a
 
      07-28-2004
Hi everyone,
I'd like to know when and how signals are used (e.g. SIGFPE, SIGABRT,
SIGTERM, SIGSEGV, SIGINT)? Thank you so much.


 
Reply With Quote
 
 
 
 
Ganesh
Guest
Posts: n/a
 
      07-28-2004
"Jackie" <(E-Mail Removed)> wrote in message news:<l_GNc.962$(E-Mail Removed) k.net>...
> Hi everyone,


Hello!

> I'd like to know when and how signals are used (e.g. SIGFPE, SIGABRT,
> SIGTERM, SIGSEGV, SIGINT)? Thank you so much.


Signals provide a way to handle asynchronous (and unexpected) events.
A signal (number) is associated with an event. Like:

SIGFPE: associated with the event "Floating Point Error (FPE)". For
example: This occurs when the process tries to divide a number by zero
as in p=5/0.

SIGSEGV: associated with the event "Segment Violation". Is generated
when the process tries to access an illegal memory segment (this is a
common error with pointers).

SIGINT: This is generated by the terminal (console) when the terminals
interrupt key (usually Ctrl+C) is pressed.

Every signal has an associated default action, that takes place when
the signal is generated. But this can be changed using one of the
signal functions (like signal(), sigaction()). These functions allow
us to specify a user defined action (function) for handling a signal.
Now after installing our own handler, if the signal occurs.. This time
the user specified action will be taken to handle that signal.

However there are some signals which cannot be caught and handled...
Like: SIGKILL, SIGSTOP.

Plzz refer to ur systems manual for more information...

- Gana
 
Reply With Quote
 
 
 
 
Jackie
Guest
Posts: n/a
 
      07-28-2004

> Signals provide a way to handle asynchronous (and unexpected) events.
> A signal (number) is associated with an event. Like:
>
> SIGFPE: associated with the event "Floating Point Error (FPE)". For
> example: This occurs when the process tries to divide a number by zero
> as in p=5/0.


Thank you so much for replying. Can you give me a code example that shows
how one may be able to use the signals in <signal.h> to handle asynchronous
(and unexpected) events? Should I call this function: "int raise(int sig)"?
I very much like to know how to use signals in a c code since the signals
are mentioned in the standard library.


 
Reply With Quote
 
kal
Guest
Posts: n/a
 
      07-28-2004
"Jackie" <(E-Mail Removed)> wrote in message news:<toLNc.1067$(E-Mail Removed) nk.net>...

> Thank you so much for replying. Can you give me a code example that shows
> how one may be able to use the signals in <signal.h> to handle asynchronous
> (and unexpected) events? Should I call this function: "int raise(int sig)"?
> I very much like to know how to use signals in a c code since the signals
> are mentioned in the standard library.


That confuses me a lot too. Even the function prototype
takes a while to figure out.

Let us see now.

void (*signal(int sig, void (*func)(int)))(int);

singal is a function taking two parameters and teturning
a pointer to a function.

The paramters are (1) an int, and (2) a pointer to a
function taking an int and returning nothing.

The return value is a pointer to a function taking an int
and returning nothing.

Does this seem ok?

Now, how do I declare a pointer to this signal function?
 
Reply With Quote
 
Dave Vandervies
Guest
Posts: n/a
 
      07-28-2004
In article <l_GNc.962$(E-Mail Removed) >,
Jackie <(E-Mail Removed)> wrote:
>Hi everyone,
>I'd like to know when and how signals are used (e.g. SIGFPE, SIGABRT,
>SIGTERM, SIGSEGV, SIGINT)? Thank you so much.


They're typically raised by the system to indicate asynchronous events
that your program might be interested in. (You can also raise them
synchronously by calling raise(), which has the effect of invoking the
appropriate signal handler for the signal number you give it.)

When a signal is raised, the handler for that signal gets invoked; you
can install a signal handler to do something you want done when a signal
is raised. There's not much that you can depend on being able to do
in a signal handler, so usually the best way to do things is to set a
flag that your program checks occasionally and does appropriate things
(and then clears it) if it finds that it's set.

SIGFPE, SIGSEGV, and SIGILL are only raised after your program has somehow
invoked undefined behavior, so if your system supports it you can catch
these and your signal handler can find and attempt to fix the source of
the problem.

SIGABRT indicates an abnormal termination. (This is raised by calling
abort(), which fgets called for assert failures.) Trapping this would
be useful for, f'rexample, dumping post-mortem debugging information if
you run into an internal error.
(If it's raised as a result of calling abort(), it's considered a
synchronous signal, so you can call any library function other than
raise(). It's not immediately clear to me whether you're allowed to call
abort() again (which would apparently call raise() again), but it's also
not clear why you would want to.)

That leaves SIGINT and SIGTERM, for interactive attention requests and
termination requests, as the only ones that are really portably useful
in a working program[1]. Typically, if you're doing a long-running
computation that you want to be able to interrupt (to change the
parameters or provide additional input - if you want the program to be
able to run when the user doesn't have anything to say, this is a good way
to work around the fact that any stdio input will wait until there's input
there) or that needs to be able to be shut down cleanly in the middle of
a run, you'd install handlers that set an appropriate flag, and check the
flags and act appropriately at some appropriate point in your computation.
Here's an (oversimplified) example program of how you might want to
use them:
--------
/*Example of using SIGINT and SIGTERM in a program with a long-running
computation
Not compiled or tested, for instructional use only, standard disclaimers
apply
Written by Dave Vandervies 2004-07-28 to be used, abused, bent, folded,
or mutilated as appropriate.
*/

/*Alphabetical: the One True Order for #including standard headers.*/
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

volatile sig_atomic_t stop;
volatile sig_atomic_t interrupt;

void sighandler(int signum)
{
if(signum==SIGINT)
interrupt=1;
if(signum==SIGTERM)
stop=1;

/*Calling signal like this is specifically permitted (N869 7.14.1.1#5,
see also #4); whether it's needed is implementation-defined (N869
7.14.1.1#3).
*/
signal(signum,sighandler);
}

int do_long_computation(void)
{
unsigned long i,j;
for(i=0;i<ULONG_MAX;i++)
{
for(j=0;j<ULONG_MAX;j++)
{
if(stop)
{
printf("Termination request received, exiting (i=%lu, j=%lu)\n",i,j);
/*If we have any cleanup to do (saving a checkpoint file,
perhaps), we do it here
*/
return 1;
}
if(interrupt)
{
char buf[64];
unsigned long new_val;

printf("i=%lu, j=%lu\n",i,j);
fputs("You wanted a new value for i? Enter it now: ",stdout)
fflush(stdout);
fgets(buf,sizeof buf,stdin);
errno=0;
new_val=strtol(buf,NULL,0);
if(new_val==ULONG_MAX && errno==ERANGE)
puts("Invalid value, using old value");
else
i=new_val;

interrupt=0;
}

/*Do a part of the long computation here*/

}
}

return 0;
}

int main(void)
{
/*Pointer to function of the appropriate type for a signal handler.
We use this to check the return value of signal() against multiple
possible returns.
*/
void (*oldhandler)(int);

/*Start by installing the appropriate signal handlers (we want to do
this before we get into anything nontrivial; if we had enough setup
to justify a separate "initialize" function this would go there)
*/

/*This is, I'm told, the safe way to install a SIGINT handler on unix-
like systems (so that an interrupt from the terminal interrupts the
foreground program as the user expects and not something running in
the background), and does no harm elsewhere.
*/
/*signal() returns the old handler for this signal, or SIG_ERR on
failure.
*/
oldhandler=signal(SIGINT,sighandler);
if(oldhandler==SIG_IGN)
{
puts("SIGINT was ignored (perhaps we're in the background?), re-ignoring\n");
signal(SIGINT,SIG_IGN);
}
else if(oldhandler==SIG_ERR)
{
fputs("Unable to install handler for SIGINT, running in uninterruptible mode\n",stderr);
}

/*Since we're only checking against SIG_ERR here, we can use the return
value of signal() directly
*/
if(signal(SIGTERM,sighandler)==SIG_ERR)
{
fputs("Unable to install handler for SIGTERM, left with system default\n (this may cause an unclean shutdown)\n",stderr);
}


/*Now that we've got our signal handlers installed, we can start our
long computation secure in the knowledge that the user can cleanly
interrupt it (usually ^C on commonly used interactive platforms) or
terminate it (in a system-dependent manner), or at least has been
warned that attempting to do so won't work.
*/
if(do_long_computation())
{
/*Nonzero return indicates early interruption, so indicate that with
exit status
*/
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
--------


dave

[1] This is actually a slight stretch, since an implementation that isn't
attempting to provide nonzero QOI can legally implement the signal
handling code as:
--------
void SIG_DFL(int i) {}
void SIG_IGN(int i) {}
void SIG_ERR(int i) {}

void (*signal(int signum,void (*handler)(int)))(int)
{
/*SIG_IGN is the only signal handler we can install without an error*/
if(handler!=SIG_IGN)
return SIG_ERR;
else
/*We know the previous handler was SIG_IGN*/
return SIG_IGN;
}

int raise(int signum)
{
/*We know the handler is SIG_IGN, so the as-if rule says we can
get away with doing nothing here.
Return value of 0 means we successfully did nothing.
*/
return 0;
}
--------
But you're not likely to encounter implementations that attempt to be
useful and don't support signals, unless the underlying system doesn't
provide a way to implement them or makes it pathologically difficult.

--
Dave Vandervies http://www.velocityreviews.com/forums/(E-Mail Removed)
I'm not sure how I can describe it so as to be free from the possibility of
perverse interpretation; ultimately, communication can only occur between
people who want to communicate. --Anton van Straaten in comp.lang.scheme
 
Reply With Quote
 
Dave Vandervies
Guest
Posts: n/a
 
      07-28-2004
In article <(E-Mail Removed) >,
kal <(E-Mail Removed)> wrote:
>"Jackie" <(E-Mail Removed)> wrote in message
>news:<toLNc.1067$(E-Mail Removed) ink.net>...
>
>> Thank you so much for replying. Can you give me a code example that shows
>> how one may be able to use the signals in <signal.h> to handle asynchronous
>> (and unexpected) events? Should I call this function: "int raise(int sig)"?


raise() lets you synchronously raise a signal within your program, and
is approximately equivalent to calling the appropriate function directly
(but knowing what the currently installed handler for the signal is
may be nontrivial). It's not needed if you're receiving asynchronous
signals generated outside your program.

>> I very much like to know how to use signals in a c code since the signals
>> are mentioned in the standard library.

>
>That confuses me a lot too. Even the function prototype
>takes a while to figure out.
>
>Let us see now.
>
>void (*signal(int sig, void (*func)(int)))(int);
>
>singal is a function taking two parameters and teturning
>a pointer to a function.
>
>The paramters are (1) an int, and (2) a pointer to a
>function taking an int and returning nothing.
>
>The return value is a pointer to a function taking an int
>and returning nothing.
>
>Does this seem ok?


Yep. The "function taking an int and returning nothing" part is the
signal handler type; you give it a pointer to the new signal handler,
and it returns a pointer to the old signal handler (or SIG_ERR, a special
value of the appropriate type that indicates a failure).


>Now, how do I declare a pointer to this signal function?


Use typedef.

typedef void (*sighandler_t)(int);
sighandler_t (*pointer_to_signal_function)(int,sighandler_t) = signal;

(But why would you want to, unless you're trying to wrap your brain
around function pointers?)


dave

--
Dave Vandervies (E-Mail Removed)
I'm not sure how I can describe it so as to be free from the possibility of
perverse interpretation; ultimately, communication can only occur between
people who want to communicate. --Anton van Straaten in comp.lang.scheme
 
Reply With Quote
 
Ganesh
Guest
Posts: n/a
 
      07-29-2004
"Jackie" <(E-Mail Removed)> wrote in message news:<toLNc.1067$(E-Mail Removed) nk.net>...
> > Signals provide a way to handle asynchronous (and unexpected) events.
> > A signal (number) is associated with an event. Like:
> >
> > SIGFPE: associated with the event "Floating Point Error (FPE)". For
> > example: This occurs when the process tries to divide a number by zero
> > as in p=5/0.

>
> Thank you so much for replying. Can you give me a code example that shows
> how one may be able to use the signals in <signal.h> to handle asynchronous
> (and unexpected) events? Should I call this function: "int raise(int sig)"?
> I very much like to know how to use signals in a c code since the signals
> are mentioned in the standard library.



/*----------------8<------------------------------------->8------------------*/

/* A simple code example to demonstrate the use of signal() function*/

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

void sighandler(int signum);

void sighandler(int signum)
{
static count=0;

if (signum == SIGINT) /* Since the same handler(function)
can be installed to handle more than one signal, the 2nd argument <int
signum> provides a way to know which signal has invoked this handler
at that time */
{
printf("Caught SIGINT signal...\n");
count++;
}

else printf("This will never get printed here...\n");

/* exit after catching the SIGINT 3 times */
if (count == 3) exit(0);
}

main()
{
signal(SIGINT, sighandler); /* This function installs
"sighandler" to handle the SIGINT and returns a pointer to the
previously installed handler for this signal (which is the default
handler SIG_DFL initially). If we try to install another handler to
handle SIGINT at some other time... Then the new handler replaces this
current one and returns a pointer to this handler. */

/* Now pressing the terminals interrupt key (usually Ctrl+C) will
generate the SIGINT signal. */

for(;/* wait for the signal */ {}
}

/*----------------8<------------------------------------->8------------------*/


- Gana
 
Reply With Quote
 
goose
Guest
Posts: n/a
 
      07-29-2004
(E-Mail Removed) (Ganesh) wrote in message news:<(E-Mail Removed). com>...
> "Jackie" <(E-Mail Removed)> wrote in message news:<toLNc.1067$(E-Mail Removed) nk.net>...
> > > Signals provide a way to handle asynchronous (and unexpected) events.
> > > A signal (number) is associated with an event. Like:
> > >
> > > SIGFPE: associated with the event "Floating Point Error (FPE)". For
> > > example: This occurs when the process tries to divide a number by zero
> > > as in p=5/0.

> >
> > Thank you so much for replying. Can you give me a code example that shows
> > how one may be able to use the signals in <signal.h> to handle asynchronous
> > (and unexpected) events? Should I call this function: "int raise(int sig)"?
> > I very much like to know how to use signals in a c code since the signals
> > are mentioned in the standard library.

>
>
> /*----------------8<------------------------------------->8------------------*/
>
> /* A simple code example to demonstrate the use of signal() function*/
>
> #include<stdio.h>
> #include<signal.h>
>
> void sighandler(int signum);
>
> void sighandler(int signum)
> {
> static count=0;


static sig_atomic_t count=0;
>
> if (signum == SIGINT) /* Since the same handler(function)
> can be installed to handle more than one signal, the 2nd argument <int
> signum> provides a way to know which signal has invoked this handler
> at that time */
> {
> printf("Caught SIGINT signal...\n");


dangerous calling printf ni a signal handler, no?

> count++;
> }
>
> else printf("This will never get printed here...\n");
>
> /* exit after catching the SIGINT 3 times */
> if (count == 3) exit(0);
> }
>
> main()


int main (void)

> {
> signal(SIGINT, sighandler); /* This function installs
> "sighandler" to handle the SIGINT and returns a pointer to the
> previously installed handler for this signal (which is the default
> handler SIG_DFL initially). If we try to install another handler to
> handle SIGINT at some other time... Then the new handler replaces this
> current one and returns a pointer to this handler. */
>
> /* Now pressing the terminals interrupt key (usually Ctrl+C) will
> generate the SIGINT signal. */
>
> for(;/* wait for the signal */ {}
> }
>


dont you think it might be better for the loop in main to check the
static variable and end when the condition is met? this will allow
you to release all resources before exiting (not that there are
any in this trivial program, but one never knows what maintenance
programmer will come along and turn this into a non-trivial application).

Its also neater to have an easily findable exit from main.

goose,
 
Reply With Quote
 
Dave Vandervies
Guest
Posts: n/a
 
      07-29-2004
In article <(E-Mail Removed) >,
goose <(E-Mail Removed)> wrote:
>(E-Mail Removed) (Ganesh) wrote in message
>news:<(E-Mail Removed) .com>...


>/*----------------8<------------------------------------->8------------------*/
>>
>> /* A simple code example to demonstrate the use of signal() function*/
>>
>> #include<stdio.h>
>> #include<signal.h>
>>
>> void sighandler(int signum);
>>
>> void sighandler(int signum)
>> {
>> static count=0;

>
> static sig_atomic_t count=0;


Even this isn't enough for what he's doing; this makes it valid to store
a value in count, but he's also accessing it to get the previous value
with the increment.

Quoth N869 (7.14.1.1):
# [#5] If the signal occurs other than as the result of
# calling the abort or raise function, the behavior is
# undefined if the signal handler refers to any object with
^^^^^^^^^^^^^^^^^^^^^^^^^
# static storage duration other than by assigning a value to
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^
# an object declared as volatile sig_atomic_t, or the signal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# handler calls any function in the standard library other
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^
# than the abort function or the signal function with the
^^^^
# first argument equal to the signal number corresponding to
# the signal that caused the invocation of the handler.
# Furthermore, if such a call to the signal function results
# in a SIG_ERR return, the value of errno is
# indeterminate.19


>> if (signum == SIGINT) /* Since the same handler(function)
>> can be installed to handle more than one signal, the 2nd argument <int
>> signum> provides a way to know which signal has invoked this handler
>> at that time */
>> {
>> printf("Caught SIGINT signal...\n");

>
>dangerous calling printf ni a signal handler, no?


'Tis. See the second marked part of the quote from n869 above.


>> count++;
>> }
>>
>> else printf("This will never get printed here...\n");


Unless somebody installs the handler for something other than SIGINT...

>>
>> /* exit after catching the SIGINT 3 times */
>> if (count == 3) exit(0);


What happens if the implementation resets the signal handler to SIG_DFL
when the signal is raised? (Whether it does this is implementation-
defined, see N869 7.14.1.1#3.)

>> }
>>
>> main()

>
>int main (void)


This is good form, but it's not the same importance as your other
corrections. (`int main()' is the minimal form required by C99, but for
C90 `main()' is treated by the compiler the same way as `int main(void)',
the latter is merely generally accepted to be better style.)

>> {
>> signal(SIGINT, sighandler); /* This function installs
>> "sighandler" to handle the SIGINT and returns a pointer to the
>> previously installed handler for this signal (which is the default
>> handler SIG_DFL initially). If we try to install another handler to
>> handle SIGINT at some other time... Then the new handler replaces this
>> current one and returns a pointer to this handler. */


What happens if signal() fails here?


>> /* Now pressing the terminals interrupt key (usually Ctrl+C) will
>> generate the SIGINT signal. */
>>
>> for(;/* wait for the signal */ {}
>> }
>>

>
>dont you think it might be better for the loop in main to check the
>static variable and end when the condition is met? this will allow
>you to release all resources before exiting (not that there are
>any in this trivial program, but one never knows what maintenance
>programmer will come along and turn this into a non-trivial application).
>
>Its also neater to have an easily findable exit from main.


It also makes it possible to write the signal handler without invoking
undefined behavior.
Better would be to have a sig_atomic_t used as an "interrupt happened"
flag at file scope that the signal handler simply sets:
--------
static volatile sig_atomic_t interrupted;
void sighandler(int signum)
{
/*This calls abort() if we get a signal other than SIGINT; this
is one of the few things that's guaranteed to be valid inside
a signal handler (N869 7.14.1.1#4, #5)
*/
assert(signum==SIGINT);
interrupted=1;
signal(signum,sighandler);
}
--------

Then write the loop in main to check this flag and do "we've been
interrupted" stuff when the flag is set:
--------
while(1)
{
static int count=0;

/*Normally we'd want to be doing something useful inside this loop*/
while(!interrupted)
;

printf("Caught SIGINT signal...\n");
if(++count>=3)
break;

interrupted=0;
}
--------


dave

--
Dave Vandervies (E-Mail Removed)
We also should expect to learn much of value from nonbelievers in the
process. They too, it is rumored, are made in the image of God.
--Daniel Taylor, _The Myth of Certainty_
 
Reply With Quote
 
Villy Kruse
Guest
Posts: n/a
 
      07-30-2004
On Thu, 29 Jul 2004 16:54:43 +0000 (UTC),
Dave Vandervies <(E-Mail Removed)> wrote:


>
> It also makes it possible to write the signal handler without invoking
> undefined behavior.


You still have behaviour which isn't well defined. If a new signal is
reaised after sighandler has been entered but before it has called signal
to reinstall the handler you don't know what would happen, unless the
implementation defines what would happen. Also, the side effect on
a pending input operation isn't specified. On some systems the io
operation might terminate with an error, while one some other system it
won't. If the io operation doesn't terminate then the program won't
come around to test the "interrupted" variable until the io operation
terminates for other reasons. In my opinion, signal is a minefield of
undefined and implementation defined behaviour.


> Better would be to have a sig_atomic_t used as an "interrupt happened"
> flag at file scope that the signal handler simply sets:
> --------
> static volatile sig_atomic_t interrupted;
> void sighandler(int signum)
> {
> /*This calls abort() if we get a signal other than SIGINT; this
> is one of the few things that's guaranteed to be valid inside
> a signal handler (N869 7.14.1.1#4, #5)
> */
> assert(signum==SIGINT);
> interrupted=1;
> signal(signum,sighandler);
> }
> --------
>
> Then write the loop in main to check this flag and do "we've been
> interrupted" stuff when the flag is set:
> --------
> while(1)
> {
> static int count=0;
>
> /*Normally we'd want to be doing something useful inside this loop*/
> while(!interrupted)
> ;
>
> printf("Caught SIGINT signal...\n");
> if(++count>=3)
> break;
>
> interrupted=0;
> }
> --------
>




Villy
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Question about signals root C Programming 4 10-10-2009 03:28 AM
[Question] signals mark C Programming 12 07-27-2009 09:29 AM
Testbench Question: Internal signals. BLF VHDL 6 02-06-2009 02:40 AM
Question about signals Ardni VHDL 4 11-05-2008 08:54 AM
Question to resolved signals, transport delay lundril@gmx.de VHDL 6 05-09-2006 10:43 AM



Advertisments