Apache Semaphore issue


Semaphore issues
This is one of the rarest conditions which I came across. The webserver failed to load with following error messages in the server log file. The server had fairly good uptime and was a busy server.

============================================================
[emerg] (28)No space left on device: Couldn't create accept lock
[notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[notice] Digest: generating secret for digest authentication ...
[notice] Digest: done
[warn] pid file /etc/httpd/run/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
[emerg] (28)No space left on device: Couldn't create accept lock
 ===========================================================


However the disk space as well as quota limit were  fine.  On a detailed analysis, it is found to be  a semaphore issue.


 A semaphore is an inter-process communication tool that is used by Apache to communicate with its child processes. Semaphore marks memory locations as locked and may not release it upon completion of process. In most case, if parent process dies before the child.


Due to the marking of  too many memory locations as being used while they are not,  the system will run out of memory locations after some time. This can happen in very busy servers with high uptime. In the previous case, the error message indicates that the apache server fails to allocate semaphores for new child processes.Check to see how many semaphores are currently in use. If Apache is running correctly, you should see something like this

# ipcs -s

If Apache is stopped, and you still see these semaphores, then you can safely kill them by running this command for each semaphore id (in the second column)

#ipcrm -s <semid>

To destroy all semaphores, you can run this from the command line (with “apache” being the apache-user:

#for semid in `ipcs -s | grep apache | cut -f2 -d" "`; do ipcrm -s $semid; done

or

#ipcs -s | grep apache | perl -e ‘while (<STDIN>) { @a=split(/\s+/); print `ipcrm sem $a[1]`}’

#ipcs -s | grep nobody | perl -e ‘while () { @a=split(/\s+/); print `ipcrm sem $a[1]`}’
 
or

#ipcs -m | grep nobody | perl -e ‘while () { @a=split(/\s+/); print `ipcrm -m $a[1]`}’

OR

for i in `ipcs -s | awk /httpd/ {print $2}’`; do (ipcrm -s $i); done

Increase semaphore limit
To view the current parameters:

#ipcs -l

To change these parameters, modify the file /etc/sysctl.conf and add the following lines:

kernel.msgmni = 1024
 
kernel.sem = 250 256000 32 1024


Then load these settings with the command:

#sysctl -p


5 comments:

Anonymous said...

This seems like a very serious bug for apache to have. A semaphore-based memory leak in production server software? There must be a way to force this issue, or at least things that cause it to occur sooner/more often. Known bug? Etc.?

Anonymous said...

Yeah I have this issue also, I just discovered. Every time Apache gets a "start" or "restart" message, it leaks 1 semaphore. So for example, if you start Apache and it has 8 semaphores by default, then send it a "restart" command, or "stop" and "start" again, it will list 9 semaphores. But if you "stop" it then, instead of listing 0 semaphores, it will list 1. So essentially, a workaround script would need to "stop" Apache, then delete all the semaphores extant as "Apache", then "start" Apache again, and you would have to use that script instead of the Apache "restart" command every time you wanted to restart Apache.

So basically, you can make a bash script to do this in order:
1. cd to your favorite empty directory
2. systemctl stop httpd.service
3. ipcs | grep apache | awk '{print $2}' > sem.txt
4. for i in `cat sem.txt`; do { ipcrm -s $i; }; done;
5. (optional) rm sem.txt
6. systemctl start httpd.service

And use that bash script as your newfangled "restart" command for Apache.

Anonymous said...

^ I didn't mention it, but special thanks to http://www.linuxquestions.org/questions/linux-server-73/apache-no-space-left-on-device-couldn%27t-create-the-proxy-mutex-4175488130/#post5081543 .

Here's the bash script I use now, which results consistently in only 1 semaphore being used. You can see how it works. So far, so functional, for me. Just CD to a different directory where you want it to store the < 1 KB sem.txt file.

#!/bin/bash
cd /home/programs/apache_modules
systemctl stop httpd.service
ipcs | grep apache | awk '{print $2}' > sem.txt
for i in `cat sem.txt`; do { ipcrm -s $i; }; done;
systemctl start httpd.service

Anonymous said...

Why are you restarting apache after clearing semaphors, wound that mess up existing running apache processes.

Biswajit Das said...

Nice articel about , This article help me very well. Thank you. Also please check my article on my site Know All About Htaccess Tutorial. In link article we will learn about htaccess error document.