A memory leak is present in all version of sancp at two levels. An immediate fix for the lower level Memory Leak is included in this post.
Details:
The memory leak is present in the code at two levels 1) the lower level that is responsible for allocating 'pools' of memory, does not free them at program termination. 2) The upper level that is responsible for increasing the memory does not offer a means to reduce the memory consumed after any period of time.
Lower Level Memory Leak:
Memory Leak in Memory.cpp. Code to free allocated memory is not present in destructor. (see New Code: below)
Lower Level Workaround:
Allow sancp to continue running until the system restarts. Apply the New Code recommended and have the new binary tested and in place prior to restarting the system.
(See: Lower Level Discussion further below)
Upper Level Memory Leak
Deficient Memory Management Option to Reduce Allocated Memory without program termination.
Upper Level Workaround:
Upon successfully applying the Memory.cc.patch, compiling and testing; schedule a restart of sancp 1.6.1 every "restart interval" ( i.e. when all connections are to be written to disk.) This can be accomplished using a 'cron job' to send a termination signal to each sancp process and then restarting each. For environments already monitoring the sancp process, observing the amount of memory sancp is currently consuming can be a accurate measurement of when to restart the process, should that be desired. (See: Upper Level Discussion further below 'New Code')
Lower Level Discussion:
SANCP needs all the memory it requests and doesn't intend to release any throughout the life of the program. Most environments provide more than enough memory for sancp to work with, however, if sancp is ever restarted, (i.e. your environment requires that you repeatedly stop and restart sancp) then your system will require a full reboot in order for the system to reclaim its memory.
The pool of memory starts out small about 1k and then doubles each time it is exhausted. The doubling naturally stops once a near maximum number of concurrent connections has been reached. The goal of the code is to acquire enough memory to immediately work with without requiring repeated requests for more memory, (i.e. during peak load) The section of code in question can be found below; where the current code is shown followed by the new code which fixes the leak at the lowest level.
// //Current Code: (all versions sancp-1.6.2 and earlier) // CMemoryPool::~CMemoryPool() { //DeleteCriticalSection(&m_critsec); } // //New Code: ( frees object CMemoryPool's 'CBuffer object's linked list') // CMemoryPool::~CMemoryPool() { //DeleteCriticalSection(&m_critsec); CBuffer *pBuffer=0; unsigned int dwFreeCount; dwFreeCount = m_freePool.Count(); while(dwFreeCount > 0) { pBuffer = m_freePool.RemoveTail(); delete pBuffer; dwFreeCount = m_freePool.Count(); } dwFreeCount = m_usedPool.Count(); while(dwFreeCount > 0) { pBuffer = m_usedPool.RemoveTail(); delete pBuffer; dwFreeCount = m_usedPool.Count(); } }
Upper Level Discussion:
In dedicated or even heterogeneous (and therefore resource-competitive) monitoring environments, it would be poor management of resources for a primary packet collection component to 'willingly offer up' memory once an equilibrium has already been reached between all other memory-competitive processes. For if ever the case occur that resources ARE running low then a core packet processing program should not be in a position where it must began requesting memory at the very point at which a sudden peak in network load occurs. However, admittedly, since nothing in the code accounts for the undesirable event in which the system (or the administrator) has given all available resources long ago but now needs some back, an additional feature is clearly required if we wish to avoid a program restart.
In order to meet the aforementioned eco-friendly requirement; one or more forms of memory release-control should be made available, either via command-line or configuration file to occur upon receiving a 'hang-up' signal or via internal timer without a program restart.
The above post describes the lower level code change, This post provides the patch instructions to all versions of sancp 1.6.2, 1.61, and earlier. Download the attachment above (MemoryPool.cc.patch) and apply from within the sancp source directory and re-compile.
cd sancp-version/
patch < /home/your/Downloads/MemoryPool.cc.patch
Last edit: John Curry 2021-08-17