I have a simple program which uses select and stuff like that for multiplexing IO.
To interrupt the “server” process, I integrated a sig_handler which reacts on SIGINT.
Each time when memory is allocated, the containing method does the free itself or the calling method.
Using valgrind shows up, that there are some allocation aren’t freed up.
Perhaps there is no need for it, but I want to learn what would be the best way to handle the signal.
It seems that the free calls aren’t invoked when pressing STRG + C.
So it would be senseless to quit loops with a break condition, which was my first approach.
Is there any possibility to clean every thing up, before closing the whole program?
Thanks for any hints and advices.
Valgrind is just a tool for finding memory leaks, not an oracle whose advice must be heeded. Making a program “Valgrind-clean” is a worthy goal but don’t let it get out of hand. Ask yourself some questions about the program.
Does the program need to do anything when it receives a
SIGINTorSIGQUITor whatever? Does it need to do some kind of clean shutdown? For example, a server might decide to finish handling all open requests, or at least send a shutdown message to connected clients.Does a sudden termination always leave behind certain blocks? Then you can just quash those reports from Valgrind, without having to spend extra time freeing memory that’s already going to be freed.
In simple terms, there are only two reasons to call
freein a program that is about to exit.If it’s the easiest way to quash Valgrind messages (that is, without reading the Valgrind manual)
If it makes your code simpler.
Otherwise, just don’t call
freeduring program exit, since all it will do is burn CPU cycles.Handling SIGINT: I can think of four common ways to handle a SIGINT:
Use the default handler. Highly recommended, this requires the least amount of code and is unlikely to result in any abnormal program behavior. Your program will simply exit.
Use
longjmpto exit immediately. This is for folk who like to ride fast motorcycles without helmets. It’s like playing Russian roulette with library calls. Not recommended.Set a flag, and interrupt the main loop’s
pselect/ppoll. This is a pain to get right, since you have to twiddle with signal masks. You want to interruptpselect/ppollonly, and not non-reentrant functions likemallocorfree, so you have to be very careful with things like signal masks. Not recommended. You have to usepselect/ppollinstead ofselect/poll, because the “p” versions can set the signal mask atomically. If you useselectorpoll, a signal can arrive after you check the flag but before you callselect/poll, this is bad.Create a pipe to communicate between the main thread and the signal handler. Always include this pipe in the call to
select/poll. The signal handler simply writes one byte to the pipe, and if the main loop successfully reads one byte from the other end, then it exits cleanly. Highly recommended. You can also have the signal handler uninstall itself, so an impatient user can hitCTRL+Ctwice to get an immediate exit.The two simplest and most fool-proof methods are #1 and #4.
A program that exits does not have any leaks. Only a running program can have leaks. Once the program exits, all memory is freed (so there is no leak any more).