freeing memory inside a signal handler - c

I am writing an API that uses sockets. In the API, I allocate memory for various items. I want to make sure I close the sockets and free the memory in case there is a signal such as Ctrl-C. In researching this, it appears free() is not on the safe function list (man 7 signal) thus, I can't free the memory inside a signal handler. I can close the socket just fine though. Does any have any thoughts on how I can free the memory? Thank you in advance for your time.

Alternatively, don't catch the signal and just let the OS handle the cleanup as it's going to do during process cleanup anyway. You're not releasing any resources that aren't tied directly to the process, so there's no particular need to manually release them.

One technique (others exist too):
Have your program run a main processing loop.
Have your main processing loop check a flag to see if it should "keep running".
Have your signal handler simply set the "keep running" flag to false, but not otherwise terminate the program.
Have your main processing loop do the memory cleanup prior to exiting.
This has the benefit of placing both the allocation and de-allocation in blocks of code which are called with a known sequence. Doing so can be a godsend when dealing with webs of interrelated objects, and there is not going to be race condition between two processing flows trying to mess with the same object.

Don't free in the handler. Instead, indicate to your program that something needs to be freed. Then, detect that in you program, so you can free from the main context, instead of the signal context.

Are you writing a library or an application? If you're writing a library, you have no business installing signal handlers, which would conflict with the calling application. It's the application's business to handle such signals, if it wants to, and then make the appropriate cleanup calls to your library (from outside a signal-handler context).
Of course even if you're writing an application, there's no reason to handle SIGINT to close sockets and free memory. The only reasons to handle the signal are if you don't want to terminate, or if you have unsaved data or shared state (like stuff in shared memory or the filesystem) that needs to be cleaned up before terminating. Freeing memory or closing file descriptors that are used purely by your own process are not tasks you need to perform when exiting.

Related

Freeing resources when thread exits

Is it possible for a thread to clean up itself when it exits? I have the problem, that my thread calls some binary blob (via a function pointer) where I have no control about the resources it may allocate and I need some way to clean up everything as soon as the thread exits. Including memory, open file descriptors, created X-windows etc. Basically what exit() does, just that I don't want the main thread to exit.
I am currently using pthread and intercept all calls to malloc(), mmap(), open() and atexit() from inside the thread. When the thread finishes I then call the functions registered by atexit and call free(), munmap() and close() for the allocated resources.
This doesn't work however, because apparently there is a lot more going on. For example, naively closing FDs from a connection to X11 will crash the whole app.
I would like the OS to handle my thread exit as if it would be a normal process. Is that possible with pthread? If not, is there maybe another threading library that could do this?

How to recollect memory after Control + C force quit [duplicate]

In my program written with C and C++, I will new an object to fulfill the task, then delete the object.
At the moment after new object but before delete object, if the user presses ctrl+c to break the process, that will cause delete not to be called and a memory leak occurs.
What should I do to avoid this situation?
Also, if the memory was reclaimed by the OS, what about the opened files? Are they closed by the OS or should I close them manualy?
In a virtual-memory-based system, all memory is returned to the OS when a process is terminated, regardless of whether it was freed explicitly in the application code. The same might not be true of other resources, however, which you may want to free cleanly. In which case, you need to provide a custom signal handler for the SIGINT signal (which is received on Ctrl+C), see e.g. http://linux.die.net/man/2/sigaction.
Pressing CtrlC will send a SIGINT to the process, which by default does a mostly-orderly shutdown, including tearing down the memory manager and releasing all allocated heap and stack. If you need to perform other tasks then you will need to install a SIGINT handler and perform those tasks yourself.
If you allocated any SYSV Shared Memory Segments using shmget(2) then you must clean up after yourself with shmctl(2).
If you allocated any POSIX Shared Memory Segments using shm_open(3) then you must clean up after yourself with shm_unlink(3).
Both SYSV and POSIX shared memory segments persist past process termination. You can see what persists using the ipcs(1) tool.
Of course, if you haven't used any SYSV or POSIX shared memory segments, then this is all just noise. :)
You are subscribing to a rather common misconception that heap blocks that are not freed, but still accessible at the time a program exists are leaks. This is not true. Leaked blocks are those which no pointer still references, hence they can't be freed.
Through the years of playing with (and breaking) lots of perfectly good kernels, I have never managed to sufficiently break a virtual memory manager to the point where it no longer reclaimed the entire address space of a process once it exited. Unless you are working with a kernel clearly marked as 'new and experimental', you will have better luck winning the lottery than finding a system that doesn't employ an effective virtual memory manager.
Don't put cruft in your code just to get a perfect score in Valgrind. If you have no real clean up tasks to do other than freeing memory that still has valid references, you don't need to bother. If someone throws a kill -9 to your program, you won't be able to handle it and will see the old behavior repeat.
If you have file descriptors to clean up, shared locks to relinquish, streams to flush or whatever else must happen so other processes don't miss you when you're gone, by all means take care of that. Just don't go adding code that does nothing to solve a non-problem, it just seems silly to do so.
Note
This was originally going to be a comment, but is far too long and SO frowns on writing a novel one comment at a time.
When CTRL+C is pressed in a Linux console, the SIGINT signal is sent to the application which, if the signal has no handler, will terminate the program, returning all memory to the OS. This of course would make it pointless to do any freeing of memory, since all memory will freed once the program exists. However, if you would like to handle the CTRL+C SIGINT signal (maybe to write out some last data to a file or do some other cleanup), you can use the function signal() to install a function to be called when the signal is received. Check out the man page for this function if you want to learn more.
If the process quits, a memory leak will NOT normally occur.
Most of the memory you allocate will be freed on Ctrl+C. If you see memory usage not return to its prior level, it is almost certainly caused by buffered filesystem blocks.
However, you should definitely clean things up, in particular if you have used any other types of resources:
Files created in temporary directories won't be deleted. This includes /dev/shm, leaving such a file could be considered a "memory leak".
System V or posix shared memory segments won't get thrown away when your process quits. If this bothers you, clean them up specifically. Alternatively, clean them up on a subsequent run.
Normally a leak (of a persistent or semi-persistent object e.g. file) doesn't matter if a subsequent run doesn't leak more memory. So cleaning up on a future run is good enough.
Imagine a process running every 5 minutes from "cron", if it crashes on each run and leaves some mess, it's still ok provided each run cleans up the mess from the previous crash.
The OS will reclaim the memory allocated by the process when the process exits as a result of Ctrl-C or any other means.

Restarting threads from saved contexts

I am trying to implement a checkpointing scheme for multithreaded applications by using fork. I will take the checkpoint at a safe location such as a barrier. One thread will call fork to replicate the address space and signals will be sent to all other threads so that they can save their contexts and write it to a file.
The forked process will not run initially. Only when restart from checkpoint is required, a signal would be sent to it so it can start running. At that point, the threads who were not forked but whose contexts were saved, will be recreated from the saved contexts.
My first question is if it is enough to recreate threads from saved contexts and run them from there, if i assume there was no lock held, no signal pending during checkpoint etc... . Lastly, how a thread can be created to run from a known context.
What you want is not possible without major integration with the pthreads implementation. Internal thread structures will likely contain their own kernel-space thread ids, which will be different in the restored contexts.
It sounds to me like what you really want is forkall, which is non-trivial to implement. I don't think barriers are useful at all for what you're trying to accomplish. Asynchronous interruption and checkpointing is just as good as synchronized.
If you want to try hacking forkall into glibc, you should start out by looking at the setxid code NPTL uses for synchronizing setuid() calls between threads using signals. The same principle is what's needed to implement forkall, but you'd basically call setjmp instead of setuid in the signal handlers, and then longjmp back into them after making new threads in the child. After that you'd have to patch up the thread structures to have the right pid/tid values, free the excess new stacks that were created, etc.
Edit: Since the setxid code in glibc/NPTL is rather dense reading for someone not familiar with the codebase, you might instead look at the corresponding code I have in musl, called __synccall:
http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/thread/synccall.c;h=91ac5eb77322da7393f778da29d35fb3c2def15d;hb=HEAD
It uses a signal to synchronize all threads, then runs a callback sequentially in each thread one-by-one. To implement forkall, you'd want to do something like this prior to the fork, but instead of a callback, simply save jump buffers for each thread except the calling thread (you can't use a callback for this because the return would invalidate the jump buffer you just saved), then perform the fork from the calling thread. After that, you would make N new threads, and have them jump back to the old threads' saved jump buffers, and destroy their new (unneeded) stacks. You'd also need to make the right syscall to update their thread register (e.g. %gs on x86) and tid address.
Then you need to take these ideas and integrate them with glibc's thread allocation and thread stack cache framework. :-)

How to avoid memory leak when user press ctrl+c under linux?

In my program written with C and C++, I will new an object to fulfill the task, then delete the object.
At the moment after new object but before delete object, if the user presses ctrl+c to break the process, that will cause delete not to be called and a memory leak occurs.
What should I do to avoid this situation?
Also, if the memory was reclaimed by the OS, what about the opened files? Are they closed by the OS or should I close them manualy?
In a virtual-memory-based system, all memory is returned to the OS when a process is terminated, regardless of whether it was freed explicitly in the application code. The same might not be true of other resources, however, which you may want to free cleanly. In which case, you need to provide a custom signal handler for the SIGINT signal (which is received on Ctrl+C), see e.g. http://linux.die.net/man/2/sigaction.
Pressing CtrlC will send a SIGINT to the process, which by default does a mostly-orderly shutdown, including tearing down the memory manager and releasing all allocated heap and stack. If you need to perform other tasks then you will need to install a SIGINT handler and perform those tasks yourself.
If you allocated any SYSV Shared Memory Segments using shmget(2) then you must clean up after yourself with shmctl(2).
If you allocated any POSIX Shared Memory Segments using shm_open(3) then you must clean up after yourself with shm_unlink(3).
Both SYSV and POSIX shared memory segments persist past process termination. You can see what persists using the ipcs(1) tool.
Of course, if you haven't used any SYSV or POSIX shared memory segments, then this is all just noise. :)
You are subscribing to a rather common misconception that heap blocks that are not freed, but still accessible at the time a program exists are leaks. This is not true. Leaked blocks are those which no pointer still references, hence they can't be freed.
Through the years of playing with (and breaking) lots of perfectly good kernels, I have never managed to sufficiently break a virtual memory manager to the point where it no longer reclaimed the entire address space of a process once it exited. Unless you are working with a kernel clearly marked as 'new and experimental', you will have better luck winning the lottery than finding a system that doesn't employ an effective virtual memory manager.
Don't put cruft in your code just to get a perfect score in Valgrind. If you have no real clean up tasks to do other than freeing memory that still has valid references, you don't need to bother. If someone throws a kill -9 to your program, you won't be able to handle it and will see the old behavior repeat.
If you have file descriptors to clean up, shared locks to relinquish, streams to flush or whatever else must happen so other processes don't miss you when you're gone, by all means take care of that. Just don't go adding code that does nothing to solve a non-problem, it just seems silly to do so.
Note
This was originally going to be a comment, but is far too long and SO frowns on writing a novel one comment at a time.
When CTRL+C is pressed in a Linux console, the SIGINT signal is sent to the application which, if the signal has no handler, will terminate the program, returning all memory to the OS. This of course would make it pointless to do any freeing of memory, since all memory will freed once the program exists. However, if you would like to handle the CTRL+C SIGINT signal (maybe to write out some last data to a file or do some other cleanup), you can use the function signal() to install a function to be called when the signal is received. Check out the man page for this function if you want to learn more.
If the process quits, a memory leak will NOT normally occur.
Most of the memory you allocate will be freed on Ctrl+C. If you see memory usage not return to its prior level, it is almost certainly caused by buffered filesystem blocks.
However, you should definitely clean things up, in particular if you have used any other types of resources:
Files created in temporary directories won't be deleted. This includes /dev/shm, leaving such a file could be considered a "memory leak".
System V or posix shared memory segments won't get thrown away when your process quits. If this bothers you, clean them up specifically. Alternatively, clean them up on a subsequent run.
Normally a leak (of a persistent or semi-persistent object e.g. file) doesn't matter if a subsequent run doesn't leak more memory. So cleaning up on a future run is good enough.
Imagine a process running every 5 minutes from "cron", if it crashes on each run and leaves some mess, it's still ok provided each run cleans up the mess from the previous crash.
The OS will reclaim the memory allocated by the process when the process exits as a result of Ctrl-C or any other means.

How to do a cleanup after SIGKILL?

I'm working on a program which uses shared memory. Multiple instances of said program will either connect to an existing one or create it anew, and give it back to OS when there are no other processes or just detach it and terminate. I thought of using a simple counter to keep track of how many processes use it.
I'm using atexit() function to do the cleanup, however, afaik, upon receiving SIGKILL signal, processes won't do any cleanup, so if any of those processes don't terminate normally, I might never be able to clean the memory.
Is there a way to specify what to do even after a SIGKILL signal? I'm probably going to write some mechanism similar to a timer to check if processes are still alive, but I'd really like to avoid it if there is another way.
No, SIGKILL cannot be caught in any way by your application - if it could, the application could ignore it, which would defeat its purpose.
You can't catch SIGKILL.
However: you can still do cleanup, provided that cleanup is done by another process. There's lots of strategies you can go with here to let your housekeeping process see your other processes appear and disappear.
For example: you could have a Unix domain socket in a known location, which the housekeeper listens to; each slave process opens the socket to indicate it's using the shared memory segment. When a slave exits, for whatever reason, the socket will get closed. The housekeeper can see this happen and can do the cleanup.
Combined with shared memory, robust mutexes located in the shared memory segment would be a great tool. If a process dies while holding a lock on a robust mutex, the next process to attempt locking it will get EOWNERDEAD and can perform the cleanup the original owner should have performed.

Resources