Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to prevent out of memory (OOM) freezes on Linux?

Is there a way to make the OOM killer work and prevent Linux from freezing? I've been running Java and C# applications, where any memory allocated is usually used, and (if I'm understanding them right) overcommits are causing the machine to freeze. Right now, as a temporary solution, I added,

vm.overcommit_memory = 2 vm.overcommit_ratio = 10 

to /etc/sysctl.conf.

Kudos to anyone who can explain why the existing OOM killer can't function correctly in a guaranteed manner, killing processes whenever the kernel runs out of "real" memory.

EDIT -- many responses are along the lines of Michael's "if you are experiencing OOM killer related problems, then you probably need to fix whatever is causing you to run out of memory". I don't think this is the correct solution. There will always be apps with bugs, and I'd like to adjust the kernel so my entire system doesn't freeze. Given my current technical understandings, this doesn't seem like it should be impossible.

like image 966
gatoatigrado Avatar asked Jan 24 '10 03:01

gatoatigrado


People also ask

How do I protect a process from OOM killer?

protect(1) and FreeBSD OOM Killer This is used to mark a process as protected from being killed if the system exhausts the available memory and swap. The idea is that when the OOM Killer scans the processes to find out one (or more) candidate to kill to immediatly free memory, the protected processes must be skipped.

How do I stop Linux from freezing?

Common suggestions such as disable/enable swap, buy more RAM, run less processes, set limits etc. do not address the underlying problem that the kernel's low memory handling sucks camel's balls. Meanwhile, I suggest running the OOM killer manually (SysRq-F) when the system freezes as that will make it recover faster.


1 Answers

Below is a really basic perl script I wrote. With a bit of tweaking it could be useful. You just need to change the paths I have to the paths of any processes that use Java or C#. You could change the kill commands I've used to restart commands also. Of course to avoid typing in perl memusage.pl manually, you could put it into your crontab file to run automatically. You could also use perl memusage.pl > log.txt to save its output to a log file. Sorry if it doesn't really help, but I was bored while drinking a cup of coffee. :-D Cheers

#!/usr/bin/perl -w # Checks available memory usage and calculates size in MB # If free memory is below your minimum level specified, then # the script will attempt to close the troublesome processes down # that you specify. If it can't, it will issue a -9 KILL signal. # # Uses external commands (cat and pidof) # # Cheers, insertable  our $memmin = 50; our @procs = qw(/usr/bin/firefox /usr/local/sbin/apache2);  sub killProcs {     use vars qw(@procs);     my @pids = ();     foreach $proc (@procs)     {         my $filename=substr($proc, rindex($proc,"/")+1,length($proc)-rindex($proc,"/")-1);         my $pid = `pidof $filename`;         chop($pid);         my @pid = split(/ /,$pid);         push @pids, $pid[0];     }     foreach $pid (@pids)     {         #try to kill process normall first         system("kill -15 " . $pid);          print "Killing " . $pid . "\n";         sleep 1;         if (-e "/proc/$pid")         {             print $pid . " is still alive! Issuing a -9 KILL...\n";             system("kill -9 " + $pid);             print "Done.\n";         } else {             print "Looks like " . $pid . " is dead\n";         }     }     print "Successfully finished destroying memory-hogging processes!\n";     exit(0); }  sub checkMem {     use vars qw($memmin);     my ($free) = $_[0];     if ($free > $memmin)     {         print "Memory usage is OK\n";         exit(0);     } else {         killProcs();     } }  sub main {     my $meminfo = `cat /proc/meminfo`;     chop($meminfo);     my @meminfo = split(/\n/,$meminfo);     foreach my $line (@meminfo)     {         if ($line =~ /^MemFree:\s+(.+)\skB$/)         {             my $free = ($1 / 1024);             &checkMem($free);         }     } }  main(); 
like image 115
user198470 Avatar answered Oct 13 '22 23:10

user198470