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])])

Reply via email to