Hi,
yesterday after a few experiments I found my apache won't start anymore. In the
error_log
it said:
[Tue Dec 13 12:09:46 2005] [crit] (17)File exists: unable to create scoreboard
"/var/opt/apache/logs/apache_scoreboard" (name-based shared memory failure)
Deleting /var/opt/apache/logs/apache_scoreboard didn't help. Strace then
revealed:
unlink("/var/opt/apache/logs/apache_scoreboard") = 0
open("/var/opt/apache/logs/apache_scoreboard", O_WRONLY|O_CREAT|O_EXCL, 0666) =
14
stat64("/var/opt/apache/logs/apache_scoreboard", {st_mode=S_IFREG|0644,
st_size=0, ...}) = 0
shmget(17191678, 225304, IPC_CREAT|IPC_EXCL|0600) = -1 EEXIST (File exists)
Well, obviously my apache uses SysV IPC for shared mem and my experiments left
over an
existing shm segment. First, I think, the error_log message is totally
misleading since
nothing is wrong with the file. Better would be something that says which
segment is to
be removed to start apache again.
Second, why is apache using SysV IPC on my linux box at all when mmap() is
available? Is
there a reason or just chance?
Configuring the APR that comes with 2.0.55 says it can use "SysV IPC",
"Classical mmap"
or "POSIX shm_open". On linux the last one is not really an option. The manpage
to shm_open
states:
The operation of shm_open is analogous to that of open(2). name speciā
fies the shared memory object to be created or opened. For portable
use, name should have an initial slash (/) and contain no embedded
slashes.
Strace reveals that with shm_open apache want's to create
/dev/shm/var/opt/apache/logs/apache_scoreboard
as shared mem. That fails because the directory do not exists. Thus, on linux
the name
parameter to shm_open should not contain embedded slashes.
I think the configure process should check that.
But the mmap shared mem implementation works (by now) on my linux box:
unlink("/var/opt/apache/logs/apache_scoreboard") = -1 ENOENT (No such file or
directory)
open("/var/opt/apache/logs/apache_scoreboard", O_RDWR|O_CREAT|O_EXCL, 0666) = 14
ftruncate(14, 225312) = 0
lseek(14, 225312, SEEK_SET) = 225312
mmap2(NULL, 225312, PROT_READ|PROT_WRITE, MAP_SHARED, 14, 0) = 0x4063d000
close(14) = 0
I think this is better since it avoids hidden shared mem keys or ids.
Why APR configure chooses SysV IPC in the first place? configure.in looks like:
APR_BEGIN_DECISION([namebased memory allocation method])
APR_IFALLYES(header:sys/mman.h func:mmap func:munmap,
[havemmaptmp="1"
APR_DECIDE(USE_SHMEM_MMAP_TMP,
[Classical mmap() on temporary file])])
APR_IFALLYES(header:sys/mman.h func:mmap func:munmap func:shm_open dnl
func:shm_unlink,
[havemmapshm="1"
APR_DECIDE(USE_SHMEM_MMAP_SHM,
[mmap() via POSIX.1 shm_open() on temporary file])])
APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl
func:shmget func:shmat func:shmdt func:shmctl,
[haveshmget="1"
APR_DECIDE(USE_SHMEM_SHMGET, [SysV IPC shmget()])])
...
APR_END_DECISION
This explains it. SysV IPC wins because it is simply the last.
If what I said makes sense and there is no reason against "Classical mmap" then
maybe
the attached patch can be considered. It changes configure and configure.in.
I have also checked the APR that comes with 2.1.8. The decision process is the
same.
My box is suse linux 9.2 with linux 2.6.8 and glibc 2.3.3.
Torsten
--- httpd-2.0.55/srclib/apr/configure~ 2005-10-10 03:34:19.000000000 +0200
+++ httpd-2.0.55/srclib/apr/configure 2005-12-13 12:24:10.559527211 +0100
@@ -29272,7 +29272,7 @@
ac_decision=''
ac_rc=yes
-for ac_spec in header:sys/mman.h func:mmap func:munmap; do
+for ac_spec in header:sys/mman.h func:mmap func:munmap func:shm_open func:shm_unlink; do
ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
case $ac_type in
@@ -29297,11 +29297,11 @@
done
if test ".$ac_rc" = .yes; then
:
- havemmaptmp="1"
- ac_decision='USE_SHMEM_MMAP_TMP'
-ac_decision_msg='Classical mmap() on temporary file'
-ac_decision_USE_SHMEM_MMAP_TMP=yes
-ac_decision_USE_SHMEM_MMAP_TMP_msg='Classical mmap() on temporary file'
+ havemmapshm="1"
+ ac_decision='USE_SHMEM_MMAP_SHM'
+ac_decision_msg='mmap() via POSIX.1 shm_open() on temporary file'
+ac_decision_USE_SHMEM_MMAP_SHM=yes
+ac_decision_USE_SHMEM_MMAP_SHM_msg='mmap() via POSIX.1 shm_open() on temporary file'
else
:
@@ -29309,7 +29309,7 @@
fi
ac_rc=yes
-for ac_spec in header:sys/mman.h func:mmap func:munmap func:shm_open func:shm_unlink; do
+for ac_spec in header:sys/ipc.h header:sys/shm.h header:sys/file.h func:shmget func:shmat func:shmdt func:shmctl; do
ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
case $ac_type in
@@ -29334,11 +29334,11 @@
done
if test ".$ac_rc" = .yes; then
:
- havemmapshm="1"
- ac_decision='USE_SHMEM_MMAP_SHM'
-ac_decision_msg='mmap() via POSIX.1 shm_open() on temporary file'
-ac_decision_USE_SHMEM_MMAP_SHM=yes
-ac_decision_USE_SHMEM_MMAP_SHM_msg='mmap() via POSIX.1 shm_open() on temporary file'
+ haveshmget="1"
+ ac_decision='USE_SHMEM_SHMGET'
+ac_decision_msg='SysV IPC shmget()'
+ac_decision_USE_SHMEM_SHMGET=yes
+ac_decision_USE_SHMEM_SHMGET_msg='SysV IPC shmget()'
else
:
@@ -29346,7 +29346,7 @@
fi
ac_rc=yes
-for ac_spec in header:sys/ipc.h header:sys/shm.h header:sys/file.h func:shmget func:shmat func:shmdt func:shmctl; do
+for ac_spec in header:sys/mman.h func:mmap func:munmap; do
ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
case $ac_type in
@@ -29371,11 +29371,11 @@
done
if test ".$ac_rc" = .yes; then
:
- haveshmget="1"
- ac_decision='USE_SHMEM_SHMGET'
-ac_decision_msg='SysV IPC shmget()'
-ac_decision_USE_SHMEM_SHMGET=yes
-ac_decision_USE_SHMEM_SHMGET_msg='SysV IPC shmget()'
+ havemmaptmp="1"
+ ac_decision='USE_SHMEM_MMAP_TMP'
+ac_decision_msg='Classical mmap() on temporary file'
+ac_decision_USE_SHMEM_MMAP_TMP=yes
+ac_decision_USE_SHMEM_MMAP_TMP_msg='Classical mmap() on temporary file'
else
:
--- httpd-2.0.55/srclib/apr/configure.in~ 2005-02-21 01:47:18.000000000 +0100
+++ httpd-2.0.55/srclib/apr/configure.in 2005-12-13 12:24:36.855020840 +0100
@@ -731,10 +731,6 @@
havebeosarea="0"
haveos2shm="0"
APR_BEGIN_DECISION([namebased memory allocation method])
-APR_IFALLYES(header:sys/mman.h func:mmap func:munmap,
- [havemmaptmp="1"
- APR_DECIDE(USE_SHMEM_MMAP_TMP,
- [Classical mmap() on temporary file])])
APR_IFALLYES(header:sys/mman.h func:mmap func:munmap func:shm_open dnl
func:shm_unlink,
[havemmapshm="1"
@@ -744,6 +740,10 @@
func:shmget func:shmat func:shmdt func:shmctl,
[haveshmget="1"
APR_DECIDE(USE_SHMEM_SHMGET, [SysV IPC shmget()])])
+APR_IFALLYES(header:sys/mman.h func:mmap func:munmap,
+ [havemmaptmp="1"
+ APR_DECIDE(USE_SHMEM_MMAP_TMP,
+ [Classical mmap() on temporary file])])
APR_IFALLYES(header:kernel/OS.h func:create_area,
[havebeosshm="1"
APR_DECIDE(USE_SHMEM_BEOS, [BeOS areas])])