I have some code that looks like this and I'm unsure how to handle the part which will never get executed since a part of this code runs in infinite loop while waiting for connections and when I terminate the program, it exits from there only.
main(){
// do some stuff....
while(1) {
int newFD =
accept(sockFD, (struct sockaddr *)&client_addr, &client_addr_size);
if(newFD == -1) {
std::cerr << "Error while Accepting on socket" << std::endl;
continue;
}
if(!fork()) {
close(sockFD); // close child's sockfd - not needed here
// lalala do stuff send message here
close(newFD); // finally close its newFD - message sent, no use
return 0;
}
close(newFD); // close parent's newFD - no use here
}
// now execution never reaches here
close(sockFD); // so how to handle this?
freeaddrinfo(res); // and this?
return 0;
}
For these things, the OS will take care of properly releasing the resources on shutdown. However, more generally, you still need to make sure that allocated resources don't pile up during program execution, even if they are reclaimed by the OS automatically, because such a resource leak will still influence behaviour and performance of your program.
Now, concerning the resources at hand, there's no reason not to treat them like all resources in C++. The accepted rule is to bind them to an object that will release them in their destructor, see also the RAII idiom. That way, even if at some later stage someone added a break
statement the code would still behave correctly.
BTW: The more serious problem I see here is the lack of proper error handling in general.
You can, and probably should add a exit handler if your code is to be used by other people or you yourself just want it cleaner. In your exit handler you can toggle a flag that makes the while()
loop terminate. The following code will work 100% fine for this use case and is reliable and cross platform, but if you want to do more complicated things you should use proper thread safe OS specific functions or something like Boost or C++11
First declare two global variables, make them volatile so the compiler will always force us to read or write its actually memory value. If you we do not declare it volatile then it is possible the compiler can put its value in a register which will make this not work. With volatile set it will read the memory location on every loop and work correctly, even with multiple threads.
volatile bool bRunning=true;
volatile bool bFinished=false;
and instead of your while(1) {}
loop, change it to this
while(bRunning)
{
dostuff
}
bFinished=true;
In your exit handler simply set bRunning=false;
void ExitHandler()
{
bRunning=false;
while(bFinished==false) { Sleep(1); }
}
You didn't specify an operating system but it looks like you are Linux based, to set a handler on Linux you need this.
void ExitHandler(int s)
{
bRunning=false;
}
int main()
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = ExitHandler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
while(bRunning)
{
dostuff
}
...error_handling...
}
And on Windows when you are a console app its the following.
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
switch (CEvent)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
bRunning = false;
while (bFinished == false) Sleep(1);
break;
}
return TRUE;
}
int main()
{
SetConsoleCtrlHandler(ConsoleHandler, TRUE);
while(bRunning()
{
dostuff
}
...error_handling...
}
Notice the need to test and wait for bFinished
here. If you don't do this on Windows your app may not have enough time to shutdown as the exit handler is called by a separate OS specific thread. On Linux this is not necessary and you need to exit from your handler for your main thread to continue.
Another thing to note is by default Windows only gives you ~5 seconds to shut down before it terminates you. This is unfortunate in many cases and if more time is needed you will need to change the registry setting (bad idea) or implement a service which has better hooks into such things. For your simple case it will be fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With