S
Siemel Naran
Hi. I posted this question to comp.lang.c++, but am rephrasing it a bit
from what I learned and posting to comp.lang.c++.moderated for more insight.
So how do I solve my problem? I want it so that when the user presses
Ctrl-C or eds the task from task manager (or the kill command in UNIX) then
the system should shutdown gracefully. This means it should call the
destructors of all objects, which means freeing dynamic memory, closing
sockets, closing file handles, close SQL connections, etc.
My approach was to set up a signal handler using std::signal. If the signal
handler does nothing the program resumes execution at the point where the
signal was raised (kind of like the RESUME command in basic).
So one of my thoughts was to throw an exception in the signal handler, and
after returning control to the point in the function where the signal was
raised, the program would detect the exception and perform stack unwinding.
But we are not allowed to throw exceptions in signal functions. On my
compiler, Borland C++ 6 I get the message: << Project.exe faulted with
message "application-defined exception". Process Stopped. Use Step or Run to
continue. >>
My other thought was to call std::exit in the signal handler. But
unfortunately this function not destroy local objects in all stacks.
So what else can we do? This seems to be a common problem, and I'm sure
people have put much thought into it. Maybe some use of longjmp could help?
Here's my current solution, which seems to work in this special case in that
all sockets are closed, but there is no dynamic memory to release, file
handles to close, etc.
int global_s = -1;
void closesockets(int sig)
{
if (global_s != -1)
{
closesocket(global_s);
global_s = -1;
}
WSACleanup();
if (sig) exit(sig);
}
class CloseSockets
{
public:
CloseSockets() { WSADATA wsa; WSAStartup(MAKEWORD(1, 1), &wsa); }
~CloseSockets() { closesockets(0); }
private:
CloseSockets(const CloseSockets&); // not implemented
CloseSockets& operator=(const CloseSockets&); // not implemented
};
void server()
{
CloseSockets _closesockets;
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) throw std::runtime_error("fail socket");
global_s = s;
signal(SIGINT , &closesockets);
signal(SIGTERM, &closesockets);
signal(SIGABRT, &closesockets);
char myname[256];
int m = gethostname(myname, sizeof(myname));
hostent * myhost = gethostbyname(myname);
if (!myhost) throw std::runtime_error("no host");
// call to bind
// call to listen
while (true)
{
/* call to accept which creates a new socket */
while (true)
{
/* call to recv */
}
// call to closesocket
}
}
from what I learned and posting to comp.lang.c++.moderated for more insight.
So how do I solve my problem? I want it so that when the user presses
Ctrl-C or eds the task from task manager (or the kill command in UNIX) then
the system should shutdown gracefully. This means it should call the
destructors of all objects, which means freeing dynamic memory, closing
sockets, closing file handles, close SQL connections, etc.
My approach was to set up a signal handler using std::signal. If the signal
handler does nothing the program resumes execution at the point where the
signal was raised (kind of like the RESUME command in basic).
So one of my thoughts was to throw an exception in the signal handler, and
after returning control to the point in the function where the signal was
raised, the program would detect the exception and perform stack unwinding.
But we are not allowed to throw exceptions in signal functions. On my
compiler, Borland C++ 6 I get the message: << Project.exe faulted with
message "application-defined exception". Process Stopped. Use Step or Run to
continue. >>
My other thought was to call std::exit in the signal handler. But
unfortunately this function not destroy local objects in all stacks.
So what else can we do? This seems to be a common problem, and I'm sure
people have put much thought into it. Maybe some use of longjmp could help?
Here's my current solution, which seems to work in this special case in that
all sockets are closed, but there is no dynamic memory to release, file
handles to close, etc.
int global_s = -1;
void closesockets(int sig)
{
if (global_s != -1)
{
closesocket(global_s);
global_s = -1;
}
WSACleanup();
if (sig) exit(sig);
}
class CloseSockets
{
public:
CloseSockets() { WSADATA wsa; WSAStartup(MAKEWORD(1, 1), &wsa); }
~CloseSockets() { closesockets(0); }
private:
CloseSockets(const CloseSockets&); // not implemented
CloseSockets& operator=(const CloseSockets&); // not implemented
};
void server()
{
CloseSockets _closesockets;
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) throw std::runtime_error("fail socket");
global_s = s;
signal(SIGINT , &closesockets);
signal(SIGTERM, &closesockets);
signal(SIGABRT, &closesockets);
char myname[256];
int m = gethostname(myname, sizeof(myname));
hostent * myhost = gethostbyname(myname);
if (!myhost) throw std::runtime_error("no host");
// call to bind
// call to listen
while (true)
{
/* call to accept which creates a new socket */
while (true)
{
/* call to recv */
}
// call to closesocket
}
}