Monday, December 10, 2007

Cleaning Up Solaris Shared Memory

Hey There,

Today, I'm dropping down a little scriplet, and a brief line of code (if it can even be called that ;), to help out with a fairly common headache for most Solaris admins and/or users.

Generally, Solaris' shared memory allocation and cleanup functionality is relatively decent. A lot of times, you may notice that Solaris seems to be using up more than its fair share of memory which makes you worry that you don't have enough (Top and/or prstat output just don't add up).

This, however, is completely normal, and how Solaris deals with memory and swap. Solaris, once it has allocated memory for a specific program or function, will keep that memory in a pseudo-allocated state after it's done with it; the memory appears to be in use, but it actually isn't. In other words, it's keeping a seeming lock on that memory but, as soon as another process pops up that needs it, Solaris makes the memory available.

A good trick for exposing how much memory Solaris is actually using is to stress the system, like so (not always guaranteed to work):

find / -type l -name "*"

If you're dealing with Solaris' memory management model for interprocess communication and shared memory, it does the same thing.

Most of the time, you'll end up having issues because of a piece of software you're running (not blaming the software here, at all). If the software and Solaris don't play nice together, shared memory and semaphores, etc, can become "lost." By lost, I mean that they are actually still accounted for by Solaris but with no attached processes or initialization times. These chunks of IPC memory are lost to you until reboot, unless you use Solaris' IPC utilities to clean up the mess.

The following is a little bit of code to help take care of all that. It requires root privilege to run (of course) and drops shared memory segments and semaphores with no attaching processes and zeroed out start/stop times.

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License


#!/usr/bin/perl
#
# 2007 - Mike Golvach - eggi@comcast.net
#
#Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
#

$temp = $$;

system "/usr/bin/SHARED_MEM -a > /tmp/out.$temp";

open(SHARED_MEM, "</tmp/SHARED_MEM.out");
@SHARED_MEM = <SHARED_MEM>;
close(SHARED_MEM);

foreach $line (@SHARED_MEM) {
chomp($line);
@sem_shm = split(" ", $line);
if ( $line =~ /^s\s/ ) {
chomp($id = $sem_shm[1]);
chomp($nattach = $sem_shm[8]);
chomp($noentry = $sem_shm[9]);
if ( $nattach == 0 ) {
print "Removing Semaphore ID (s) $id with NATTCH value of $nattach\n";
system "ipcrm -s $id";
} elsif ( $noentry =~ /no-entry/ ) {
print "Removing Semaphore ID (s) $id with start/stop-time value of $noentry\n";
system "ipcrm -s $id";
}
} elsif ( $line =~ /^m\s/ ) {
chomp($id = $sem_shm[1]);
chomp($nattach = $sem_shm[8]);
chomp($noentry = $sem_shm[13]);
if ( $noentry =~ /no-entry/ ) {
print "Removing Shared Memory Segment ID (s) $id with NATTCH value of $nattach\n";
system "ipcrm -m $id";
} elsif ( $noentry =~ /no-entry/ ) {
print "Removing Shared Memory ID (s) $id with start/stop-time value of $noentry\n";
system "ipcrm -m $id";
}
}
}

unlink("/tmp/out.$temp");

exit;


, Mike