How to avoid out of memory to hang the system
I've seen plenty of memory related questions on Ubuntu, and to be honest I really can't understand how it is still possible to struggle with such issues.
I have 8GB RAM. I've experimenting with/without swap without much differences.
The problem is that I frequently (up to once a day) have to hard reboot my laptop because it's entirely frozen (waiting does not help). It's most probably related to RAM usage of my web browsers. Appart from this, no high demanding process is running on the laptop.
In order to experiment/reproduce:
- I "fill" my memory with Python with an infinite loop that fill a list.
- I open my (web) browser (either Chrome / Firefox), with one or more tabs.
My observations are:
- Python cannot allocate memory infinitely: it will eventually raise a
MemoryError
. - the browser in the other hand, does not give a f*** about it, and will, in my case, hang the system. I have to hard reboot the laptop then.
I'm do not understand:
- why the browser is allowed to allocate more and more memory (to the very last bit it seems)
- why does the system hangs instead of "just" killing a process.
I'm aware that swapping requires CPU, so it may hang the system for a while. That's why I disabled it, so I was thinking that the kernel would rapidly decide to kill a process.
I can't understand how such a basic usage (using browsers) could be a problem with a recent OS using 8GB RAM. Do I need to tweak my system in order to have a reliable one?
Thanks for any advice / explanation / tricks that would help.
I've solved a similar problem with a memory/cpu watcher script and just have it kill any processes that it sees that have more than x ram or y memory for longer than t seconds. That doesn't solve the problem of reserving CPU/Mem for the OS, but it is a workaround until you find a better answer (And when you do, share it with me, because I got here looking for the same thing)
#!/bin/bash
# Kill POS if we're doing stupid shit.
HOG_COUNTER=0
while true; do
# This is pulling CPU, change the awk column from 9 to something
# that you want to check against.
HOG=$(top -b -n 1 | grep pos2 | awk '$9 > 90 {print $1}')
# If the hog variable is not empty, add some counter info - we don't
# want to catch periodic spikes, we want to catch consistent offenders.
if [ ! -z "$HOG" ]; then
counter_time=$(date)
HOG_COUNTER=$(expr ${HOG_COUNTER} + 1)
echo "$counter_time - Found a hog: $HOG - ${HOG_COUNTER} counters." >> high_mem_kill_log
else
HOG_COUNTER=0
fi
# If we have more than 2 counters (3 or more) then we kill the process
# that's doing it.
if [ $HOG_COUNTER -gt 2 ]; then
kill_time=$(date)
echo "$kill_time - Found a hog: $HOG. $HOG_COUNTER counters. Killing $HOG." >> high_mem_kill_log
kill $HOG
fi
sleep 30s
done