How to handle SIGABRT without stopping the code - Unix
This is a discussion on How to handle SIGABRT without stopping the code - Unix ; Hi, I'm a newbie with signals and I need a little help.
I have a program that does arithmetic operations among integers and I
want to check when overflow happens.
I found that in the last versions of gcc, compiling ...
-
How to handle SIGABRT without stopping the code
Hi, I'm a newbie with signals and I need a little help.
I have a program that does arithmetic operations among integers and I
want to check when overflow happens.
I found that in the last versions of gcc, compiling with option -
ftrapv, when the code have to execute arithmetic operations, instead
of using the normal routines, it uses routines in libc that check for
overflow.
If overflow happens on the screen you see "Aborted" and the code
stops.
My question is:
Is it possible to have the message about overflow only but avoid that
the program stops?
In other words, if I understood correctly, how can I build a handler
function that replaces the one usually used by the OS so that SIGABRT
can be managed in a custom way?
Searching the internet, I found that it is something related to the
handler function but this topic is not so easy to manage for a newbie
like me.
TIA
Daniele
-
Re: How to handle SIGABRT without stopping the code
arkkimede@gmail.com wrote:
> Hi, I'm a newbie with signals and I need a little help.
>
> I have a program that does arithmetic operations among integers and I
> want to check when overflow happens.
>
> I found that in the last versions of gcc, compiling with option -
> ftrapv, when the code have to execute arithmetic operations, instead
> of using the normal routines, it uses routines in libc that check for
> overflow.
>
> If overflow happens on the screen you see "Aborted" and the code
> stops.
>
> My question is:
>
> Is it possible to have the message about overflow only but avoid that
> the program stops?
>
> In other words, if I understood correctly, how can I build a handler
> function that replaces the one usually used by the OS so that SIGABRT
> can be managed in a custom way?
>
> Searching the internet, I found that it is something related to the
> handler function but this topic is not so easy to manage for a newbie
> like me.
man sigaction
That function lets you set up your own signal handler.
Bjarni
--
INFORMATION WANTS TO BE FREE
-
Re: How to handle SIGABRT without stopping the code
arkkimede@gmail.com writes:
> Hi, I'm a newbie with signals and I need a little help.
>
> I have a program that does arithmetic operations among integers and I
> want to check when overflow happens.
>
> I found that in the last versions of gcc, compiling with option -
> ftrapv, when the code have to execute arithmetic operations, instead
> of using the normal routines, it uses routines in libc that check for
> overflow.
>
> If overflow happens on the screen you see "Aborted" and the code
> stops.
>
> My question is:
>
> Is it possible to have the message about overflow only but avoid that
> the program stops?
Not really, AFAIK.
> In other words, if I understood correctly, how can I build a handler
> function that replaces the one usually used by the OS so that SIGABRT
> can be managed in a custom way?
You can write a handler for SIGABRT, and install it using the signal()
function, but you won't be able to resume the operation that
overflowed. The best you can do is to use longjmp() to return to a
higher level of your program.
If you're on Linux, a good source of information on these issues is the
glibc manual (type "info libc"). It's also online at
http://www.gnu.org/software/libc/man...ode/index.html . Even if
you're not on Linux, most of what it says carries over to other
Unix-like systems. Read the chapters on "Signal handling" and
"Non-local exits". Then come back and ask if you have further
questions.
-
Re: How to handle SIGABRT without stopping the code
On 1 Nov, 01:12, Nate Eldredge wrote:
> arkkim...@gmail.com writes:
> > Hi, I'm a newbie with signals and I need a little help.
>
> > I have a program that does arithmetic operations among integers and I
> > want to check when overflow happens.
>
> > I found that in the last versions of gcc, compiling with option -
> > ftrapv, when the code have to execute arithmetic operations, instead
> > of using the normal routines, it uses routines in libc that check for
> > overflow.
>
> > If overflow happens on the screen you see "Aborted" and the code
> > stops.
>
> > My question is:
>
> > Is it possible to have the message about overflow only but avoid that
> > the program stops?
>
> Not really, AFAIK. *
>
> > In other words, if I understood correctly, how can I build a handler
> > function that replaces the one usually used by the OS so that SIGABRT
> > can be managed *in a custom way?
>
> You can write a handler for SIGABRT, and install it using the signal()
> function, but you won't be able to resume the operation that
> overflowed. *The best you can do is to use longjmp() to return to a
> higher level of your program.
>
> If you're on Linux, a good source of information on these issues is the
> glibc manual (type "info libc"). *It's also online athttp://www.gnu.org/software/libc/manual/html_node/index.html. *Even if
> you're not on Linux, most of what it says carries over to other
> Unix-like systems. *Read the chapters on "Signal handling" and
> "Non-local exits". *Then come back and ask if you have further
> questions.
I found a possible solution observing that in a child process generate
by a fork, the signal SIGABRT can be managed by a handler function
where you can do something.
In the program the child process ends (on the screen does not appear
ABORTED) then there is the execution of the father process etc.
This is a "dirty" solution because it is not possible, after the
overflow, to set any variable or flag for the father. I was
erroneously thinking to set a global variable in the handler function
so that the father, testing this variable, can understand the
overflow. This is wrong because when the child process disappear, also
the variable setting disappear so, for the father, nothing has
occurred.
The only thing that can survive to the child process is a file.
For this reason in the handler function I write a empty file
overflow.dat and the father verify the existence of this file to
understand if overflow occurred.
Comments are welcome
-
Re: How to handle SIGABRT without stopping the code
> I found a possible solution observing that in a child process generate
> by a fork, the signal SIGABRT can be managed by a handler function
> where you can do something.
Why is this not possible in the parent? Ahaa, because the library code
restores the default behaviour right after the handler returns, and
kills the process again... bah.
> In the program the child process ends (on the screen does not appear
> ABORTED) then there is the execution of the father process etc.
> This is a "dirty" solution because it is not possible, after the
> overflow, to set any variable or flag for the father. I was
> erroneously thinking to set a global variable in the handler function
> so that the father, testing this variable, can understand the
> overflow. This is wrong because when the child process disappear, also
> the variable setting disappear so, for the father, nothing has
> occurred.
Right, but you can use shared memory. See manpages for shm_open, shmget,
and mmap, which provide different mechanisms for this.
> The only thing that can survive to the child process is a file.
> For this reason in the handler function I write a empty file
> overflow.dat and the father verify the existence of this file to
> understand if overflow occurred.
That's really not very pretty. It's probably better to do what Nate
said: use setjmp to set a point in the code before you call into the
part that might abort, and have the SIGABRT handler quit back out to
that point with longjmp.
Bjarni
--
INFORMATION WANTS TO BE FREE
-
Re: How to handle SIGABRT without stopping the code
Bjarni Juliusson writes:
>> I found a possible solution observing that in a child process generate
>> by a fork, the signal SIGABRT can be managed by a handler function
>> where you can do something.
>
> Why is this not possible in the parent? Ahaa, because the library code
> restores the default behaviour right after the handler returns, and
> kills the process again... bah.
Right. The libgcc arithmetic function calls abort() when an overflow
occurs, and abort() is absolutely forbidden to return. (My system's
libc implements this by unblocking SIGABRT and then raising it; then
setting it to SIG_DFL and raising it again, and finally calling exit()
(which really should be _exit(), I think, though I don't think it can
ever be reached).) Moreover, the code and/or the compiler might rely on
this behavior, so even if you could get abort() to return, it wouldn't
necessarily have the effect of continuing your program with the right
value of the addition.
-
Re: How to handle SIGABRT without stopping the code
On Nov 2, 10:05 pm, Bjarni Juliusson wrote:
> > I found a possible solution observing that in a child process generate
> > by a fork, the signal SIGABRT can be managed by a handler function
> > where you can do something.
>
> Why is this not possible in the parent? Ahaa, because the library code
> restores the default behaviour right after the handler returns, and
> kills the process again... bah.
>
> > In the program the child process ends (on the screen does not appear
> > ABORTED) then there is the execution of the father process etc.
> > This is a "dirty" solution because it is not possible, after the
> > overflow, to set any variable or flag for the father. I was
> > erroneously thinking to set a global variable in the handler function
> > so that the father, testing this variable, can understand the
> > overflow. This is wrong because when the child process disappear, also
> > the variable setting disappear so, for the father, nothing has
> > occurred.
>
> Right, but you can use shared memory. See manpages for shm_open, shmget,
> and mmap, which provide different mechanisms for this.
>
> > The only thing that can survive to the child process is a file.
> > For this reason in the handler function I write a empty file
> > overflow.dat and the father verify the existence of this file to
> > understand if overflow occurred.
>
> That's really not very pretty. It's probably better to do what Nate
> said: use setjmp to set a point in the code before you call into the
> part that might abort, and have the SIGABRT handler quit back out to
> that point with longjmp.
>
> Bjarni
> --
>
> INFORMATION WANTS TO BE FREE
I tried to use setjmp/longjmp but I have to face to common bug of
these functions:
http://www.cs.utk.edu/~plank/plank/c...p/lecture.html
In fact, I tired to use setjmp in a function before a point where
overflow might occur but I have to use longjmp in the
SIGABRT handler (another function).
It looks like (if I well understand) that is impossible return from a
function that call setjmp.
This means that setjmp have to be used only in the main.
I do not like this because I want to produce a subroutine without put
code in the main.
-
Re: How to handle SIGABRT without stopping the code
arkkimede@gmail.com writes:
> I tried to use setjmp/longjmp but I have to face to common bug of
> these functions:
> http://www.cs.utk.edu/~plank/plank/c...p/lecture.html
>
> In fact, I tired to use setjmp in a function before a point where
> overflow might occur but I have to use longjmp in the
> SIGABRT handler (another function).
> It looks like (if I well understand) that is impossible return from a
> function that call setjmp.
> This means that setjmp have to be used only in the main.
>
> I do not like this because I want to produce a subroutine without put
> code in the main.
[Recap: You want to detect integer overflow in your program, using a
compiler option that calls abort() when an overflow occurs.]
The link says "This is a very common bug with setjmp() and longjmp() --
to use them properly, you CANNOT RETURN FROM THE PROCEDURE THAT CALLS
setjmp()."
That's an overstatement. More correctly, you cannot call longjmp()
after the function that made the corresponding call to setjmp() has
returned. So you have to ensure before returning that longjmp() won't
be called again with that jmp_buf. So if you want this overflow
handling only in one piece of your program, you can do something like
jmp_buf jb;
void handler(int sig) {
longjmp(jb, 1);
}
void do_computations(void) {
if (setjmp(jb) == 1)
printf("Oh no, an overflow happened! Starting over.");
signal(SIGABRT, handler);
compute();
signal(SIGABRT, SIG_DFL);
/* now handler() won't be called anymore, nor will longjmp(jb,1) */
return;
}
-
Re: How to handle SIGABRT without stopping the code
On Nov 3, 7:56 pm, Nate Eldredge wrote:
> arkkim...@gmail.com writes:
> > I tried to use setjmp/longjmp but I have to face to common bug of
> > these functions:
> >http://www.cs.utk.edu/~plank/plank/c...tes/Setjmp/lec...
>
> > In fact, I tired to use setjmp in a function before a point where
> > overflow might occur but I have to use longjmp in the
> > SIGABRT handler (another function).
> > It looks like (if I well understand) that is impossible return from a
> > function that call setjmp.
> > This means that setjmp have to be used only in the main.
>
> > I do not like this because I want to produce a subroutine without put
> > code in the main.
>
> [Recap: You want to detect integer overflow in your program, using a
> compiler option that calls abort() when an overflow occurs.]
>
> The link says "This is a very common bug with setjmp() and longjmp() --
> to use them properly, you CANNOT RETURN FROM THE PROCEDURE THAT CALLS
> setjmp()."
>
> That's an overstatement. More correctly, you cannot call longjmp()
> after the function that made the corresponding call to setjmp() has
> returned. So you have to ensure before returning that longjmp() won't
> be called again with that jmp_buf. So if you want this overflow
> handling only in one piece of your program, you can do something like
>
> jmp_buf jb;
>
> void handler(int sig) {
> longjmp(jb, 1);
>
> }
>
> void do_computations(void) {
> if (setjmp(jb) == 1)
> printf("Oh no, an overflow happened! Starting over.");
> signal(SIGABRT, handler);
> compute();
> signal(SIGABRT, SIG_DFL);
> /* now handler() won't be called anymore, nor will longjmp(jb,1) */
> return;
>
> }
TANK YOU VERY MUCH!
Now I'm able to manage the SIGABRT.
(Probably also yesterday the code was correct but the global
declaration of jb was destroyed by a local one (...grrrr...) and that
was the really source of the problem.
In the spirit of newsgroup and for future memory, probably in your
code there's an else instruction missing to avoid, in the case of
overflow, an infinite loop.
jmp_buf jb;
void handler(int sig) {
longjmp(jb, 1);
}
void do_computations(void)
{
if (setjmp(jb) == 1)
{
printf("Oh no, an overflow happened! Starting over.");
}
else <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
signal(SIGABRT, handler);
compute();
}
signal(SIGABRT, SIG_DFL);
/* now handler() won't be called anymore, nor will longjmp(jb,1) */
return;
}
Ciao
Daniele
-
Re: How to handle SIGABRT without stopping the code
arkkimede@gmail.com writes:
> In the spirit of newsgroup and for future memory, probably in your
> code there's an else instruction missing to avoid, in the case of
> overflow, an infinite loop.
>
> jmp_buf jb;
>
> void handler(int sig) {
> longjmp(jb, 1);
>
> }
>
> void do_computations(void)
> {
> if (setjmp(jb) == 1)
> {
> printf("Oh no, an overflow happened! Starting over.");
> }
> else <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> {
> signal(SIGABRT, handler);
> compute();
> }
> signal(SIGABRT, SIG_DFL);
> /* now handler() won't be called anymore, nor will longjmp(jb,1) */
> return;
> }
Sure, if you like. I had in mind a situation where compute() gets its
input from some external source (e.g. prompting the user), so when you
call it again it uses different data that might not provoke an overflow.
But of course you should do whatever's appropriate to your situation.