I was wondering which standards guarantee what (if anything)
with respect to C++ destructor calls, in the event that a process
receives a fatal signal ...
For example, say I write a simple C++ program which creates an object
on the stack, then calls sleep(3), and exits. The compiler does not
optimize the object out of existence ...
If I run the program, then send it a SIGINT during its sleep() call,
the destructor for the said object is *not called* ...
I realize that the default signal handler is a C call, but I would
expect it to call exit() to terminate the process, and that my compiler
would ensure the stack was properly unwound before terminating ...
Is this not the case?
And if not, how do most people mix C++ and signal handling ...
One idea I had was to have my own signal handler throw an exception ...
that way the resources might get cleaned up properly?
All comments welcome ...
Cheers,
Brian
--
Brian S Hanley | "Fear is the main source of superstition,
2A Systems Design Engineering | and one of the main sources of cruelty.
U of Waterloo /|\ To conquer fear is the beginning of wisdom."
___________________________/_\|/_\__ - Bertrand Russell _____________________
No, it isn't. There is no default handler for SIGINT, so the process is
simply terminated (it's like _exit(2) rather than exit(3)). If you want to
do something in response to SIGINT (or any other signals other than SIGKILL
or SIGSTOP, which can't be caught) you must explicitly call something like
sigaction(2) to establish a handler.
>And if not, how do most people mix C++ and signal handling ...
>
>One idea I had was to have my own signal handler throw an exception ...
>that way the resources might get cleaned up properly?
Most system resources, such as open file descriptors and virtual memory
use, are automatically reclaimed whenever a process terminates, so you
don't need to run destructors if they're just deallocating memory or
closing files (although closing files can be useful to flush buffers).
It's only necessary to perform explicit cleanup if there are things like
lock files that need to be removed or you need to send something to a
device.
You could have your handler call exit(), which should execute all
destructors.
--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
You should probably repost this in comp.std.c++, or check dejanews, as
this subject was discussed at length in that NG about a month or so
ago. Honestly the standard tried to avoid OS dependant issues like
threads and signals. However looking in Section 18.3 of the
November,1996 C++ Public Working Paper (The standard, as ratified, has
not yet been published.) it states that calling exit causes all
statically constructed objects to be destroyed.
> If I run the program, then send it a SIGINT during its sleep() call,
> the destructor for the said object is *not called* ...
> I realize that the default signal handler is a C call, but I would
> expect it to call exit() to terminate the process, and that my compiler
> would ensure the stack was properly unwound before terminating ...
>
> Is this not the case?
It seems not! I cannot find anything in the C++ standard relating to
behaviour in regards to uncaught signals.
> And if not, how do most people mix C++ and signal handling ...
>
> One idea I had was to have my own signal handler throw an exception ...
> that way the resources might get cleaned up properly?
That can cause problems in and of itself! It sounds like you want to
catch the signal yourself and specifically call exit.
Peace
Peter
: You could have your handler call exit(), which should execute all
: destructors.
This is not what I've seen with exit(). I had a small post on
comp.lang.c++ about this. I have seen this problem on Solaris and Linux.
If you think about the issue, you can understand. Since exit() is C function,
it has no idea about C++. exit() might look like this:
void exit(int st) {
do_atexit();
libc_exit_handlers();
__sys_exit(st); /* syscall */
}
I can't see any nice solution without compiler support. In C++, you
could "replace" exit() to throw an exception and catch it in the crt0.o
routine. But, this exception could be caught in main() and defeat the
purpose. The C++ library/compiler needs to supply a unwind_frame_dtor()
function for this to work every time.
Regards,
Dan
--
Dan Miner dmi...@nyx.net | | Doing
Programmer/ | | Linux
Linux Consultant | "What yonder light Windows 95 breaks?" | since
http://www.nyx.net/~dminer/ | "Free software: The New Frontier" | v0.12
I did not know that. OTOH I won't go near C with a 10 foot pole.
Indeed one should NOT throw an exception from a signal handler. Could
you cite where in the C++ standard the above statement was made, since
we were talking C++, not C. Indeed for the reasons you later state,
namely that this could cause one to reenter code that is already
executing like fflush what you are saying makes sense. I wonder if
this is hole in the C++ standard?
Thanks
Peter
My copy of CD2 is at http://www.cs.wright.edu/~pedwards/ but I can't get
to it from where I am right now to look.
Both C and C++ say the same thing regarding actions inside a signal handler.
The /only/ action that is guaranteed to be safe is modifying a variable of
type sig_atomic_t (it's an integral type of some kind). Later, outside the
handler, other routines can check that variable and take appropriate actions.
This is especially true since signal handlers may execute on a different
stack than the rest of the program. Trying to modify other data could be
dangerous. Throwing an exception would unwind the signal stack, fall off
the top, and terminate the program without ever unwinding the /real/ stack.
> Indeed for the reasons you later state,
> namely that this could cause one to reenter code that is already
> executing like fflush what you are saying makes sense. I wonder if
> this is hole in the C++ standard?
It's no more a hole in the C++ standard than it is in C. Signal handlers
are simply not the place for extensive actions. You can safely set and
clear sig_atomic_t flags to be checked by later functions, but that's it.
(Those later functions can include one that would package up a string
saying what kind of signal was caught, if you store such values in your
sig_atomic_t's, and throw that string as an exception. In this manner you
can convert a signal to an exception, if you really needed to.)
Luck++;
/dev/phil
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
Pardon me, I agree with you (what you are saying is common sense
anyway ;-) but I think you misunderstood what I meant by a hole in the
C++ standard. I could not find where in the C++ standard it stated
the things we have been discussing. I.e. that the only action that
should be taken in a signal handler is the modification of a
sig_atomic_t. And it may very well be there in CD2, and I have simply
missed it!
Thanks
Peter
Thanks, that is what I was missing! As stupid as this may sound I had
not realized that the C++ standard included the C standard unless
otherwise noted. (I wondered about that ;-) Your printf example is
very illustrative and sort of "proves" the whole thing.
Thanks
Peter
Even if it was legal, it wouldn't do what (I think) the original poster
wanted, because the C++ standard says that exit() only calls destructors
for static objects, *not* automatic (local stack) objects.
--
Ross Smith ................................... mailto:ros...@ihug.co.nz
.............. The Internet Group, Auckland, New Zealand ..............
* * * * *
"Screw up your courage. You've screwed up everything else."
Since this is UNIX (comp.unix.programmer) we are talking about,
it should be noted that POSIX specifically states what functions
can be called from within a signal handler. These functions include
such non-trivial functions as wait( ), fork( ), and exec( ).
However as noted, there is very little you can do to pass data back
to the main part of the program from within a signal handler.
Also remember that returning from the handler's for certain
signals (e.g. SIGSEGV) is not allowed.
John Kroll
> Pardon me, I agree with you (what you are saying is common sense
> anyway ;-) but I think you misunderstood what I meant by a hole in the
> C++ standard. I could not find where in the C++ standard it stated
> the things we have been discussing.
Oh! My apologies. I misread.
In CD2 it is section 1.8 (temporarily labelled [intro.execution]),
paragraph 10. When the Standard is published it will be somewhere close
to that.
I had also forgotten the POSIX extensions mentioned in a sibling reply
to your post; while I vastly prefer to use Unix, I try not to depend on
it. :-) (Oh, come on, we all know M$ won't be implementing any more
POSIX in VC++ than what's already been done, for a long time to come.)
Take care,