php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #9639 Nasty bug in mod_mm.c causes CGI POST to stop working
Submitted: 2001-03-08 17:10 UTC Modified: 2001-10-02 18:08 UTC
From: yfaktoro at nusphere dot com Assigned:
Status: Closed Package: Session related
PHP Version: 4.0.4pl1 OS: Red Hat
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: yfaktoro at nusphere dot com
New email:
PHP Version: OS:

 

 [2001-03-08 17:10 UTC] yfaktoro at nusphere dot com
On RedHat 6.2 or 7 machine with more than 67M of shared memory available
per process (this number is stored in /proc/sys/kernel/shmmax)
Compile Apache with ssl modules.
Compile mod_php into Apache --with-mm

Have 33000000 ( or anything less than 67M) in /proc/sys/kernel/shmmax on
machine where you're running Apache -> CGI POST stops working, stdin is
empty. This happens regardless of what kind of cgi script is executted
by the form, it doesn't have to be a php script. Increase the number in
/proc/sys/kernel/shmmax to something more than 67M, everything works
again. This 67M number is hardcoded in mm_create from mm library by
their configure script, which checks how much memory is available.
I have no explanation for it, because all mod_mm does in this case is
returning FAILURE if there is not enough memory. Go figure...
Here is my proposal: lets check how much memory is there before calling
mm_create in mod_mm.c by doing this: (I put the actual patch at the
bottom)

Add two new functions ( pretty much copied from mm configure)

static int test_mem_size (unsigned long size)
{
    int fd;
    void *segment;
#ifdef MM_SHMT_MMFILE
    char file[] = "./ac_test.tmp";
    unlink(file);
    if ((fd = open(file, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) == -1)
        return 0;
    if (ftruncate(fd, size) == -1)
        return 0;
    if ((segment = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
                                MAP_SHARED, fd, 0)) == MAP_FAILED) {
        close(fd);
        return 0;
    }
    munmap((caddr_t)segment, size);
    close(fd);
    unlink(file);
#endif
#ifdef MM_SHMT_IPCSHM
    if ((fd = shmget(IPC_PRIVATE, size, SHM_R|SHM_W|IPC_CREAT)) == -1)
        return 0;
    if ((segment = (void *)shmat(fd, NULL, 0)) == ((void *)-1)) {
        shmctl(fd, IPC_RMID, NULL);
        return 0;
    }
    shmdt(segment);
    shmctl(fd, IPC_RMID, NULL);
#endif
    return 1;
}
#define ABS(n) ((n) >= 0 ? (n) : (-(n)))

static unsigned long get_max_mem_size()
{
  unsigned long t, m, b;
    int d;
    int rc;
    /*
     * Find maximum possible allocation size by performing a
     * binary search starting with a search space between 0 and
     * 64MB of memory.
     */
    t = 1024*1024*64 /* = 67108864 */;
    if (test_mem_size(t))
        m = t;
    else {
        m = 1024*1024*32;
        b = 0;
        for (;;) {
            /* fprintf(stderr, "t=%d, m=%d, b=%d\n", t, m, b); */
            rc = test_mem_size(m);
            if (rc) {
                d = ((t-m)/2);
                b = m;
            }
            else {
                d = -((m-b)/2);
                t = m;
            }
            if (ABS(d) < 1024*1) {
                if (!rc)
                    m = b;
                break;
            }
            if (m < 1024*8)
                break;
            m += d;
        }
        if (m < 1024*8)
            m = 0;
    }
    return m;
}

The actual patch would look like this:

--- ext/session/mod_mm.c Fri Nov  3 07:00:49 2000
+++ ext/session/mod_mm.c Tue Feb 27 14:09:31 2001
@@ -173,9 +173,84 @@

 #define PS_MM_DATA ps_mm *data = PS_GET_MOD_DATA()

+static int test_mem_size (unsigned long size)
+{
+    int fd;
+    void *segment;
+#ifdef MM_SHMT_MMFILE
+    char file[] = "./ac_test.tmp";
+    unlink(file);
+    if ((fd = open(file, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) == -1)
+        return 0;
+    if (ftruncate(fd, size) == -1)
+        return 0;
+    if ((segment = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
+                                MAP_SHARED, fd, 0)) == MAP_FAILED) {
+        close(fd);
+        return 0;
+    }
+    munmap((caddr_t)segment, size);
+    close(fd);
+    unlink(file);
+#endif
+#ifdef MM_SHMT_IPCSHM
+    if ((fd = shmget(IPC_PRIVATE, size, SHM_R|SHM_W|IPC_CREAT)) == -1)
+        return 0;
+    if ((segment = (void *)shmat(fd, NULL, 0)) == ((void *)-1)) {
+        shmctl(fd, IPC_RMID, NULL);
+        return 0;
+    }
+    shmdt(segment);
+    shmctl(fd, IPC_RMID, NULL);
+#endif
+    return 1;
+}
+#define ABS(n) ((n) >= 0 ? (n) : (-(n)))
+static unsigned long get_max_mem_size()
+{
+  unsigned long t, m, b;
+    int d;
+    int rc;
+    /*
+     * Find maximum possible allocation size by performing a
+     * binary search starting with a search space between 0 and
+     * 64MB of memory.
+     */
+    t = 1024*1024*64 /* = 67108864 */;
+    if (test_mem_size(t))
+        m = t;
+    else {
+        m = 1024*1024*32;
+        b = 0;
+        for (;;) {
+            /* fprintf(stderr, "t=%d, m=%d, b=%d\n", t, m, b); */
+            rc = test_mem_size(m);
+            if (rc) {
+                d = ((t-m)/2);
+                b = m;
+            }
+            else {
+                d = -((m-b)/2);
+                t = m;
+            }
+            if (ABS(d) < 1024*1) {
+                if (!rc)
+                    m = b;
+                break;
+            }
+            if (m < 1024*8)
+                break;
+            m += d;
+        }
+        if (m < 1024*8)
+            m = 0;
+    }
+    return m;
+}
 static int ps_mm_initialize(ps_mm *data, const char *path)
 {
- data->mm = mm_create(0, path);
+    unsigned long m = get_max_mem_size();
+ data->mm = mm_create(m, path);
  if (!data->mm) {
   return FAILURE;

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-06-14 23:27 UTC] sniper@php.net
Does this still happen with PHP 4.0.6RC3:

http://www.php.net/~andi/php-4.0.6RC3.tar.gz

If above link does not work, change RC3 to RC4.

--Jani

 [2001-06-27 11:31 UTC] sniper@php.net
Does this happen with 4.0.6 (now that is released) ?

--Jani

 [2001-08-06 08:45 UTC] sniper@php.net
Please create this patch against the latest CVS.
And put it somewhere in the net to be downloaded and
add the url here.

--Jani

 [2001-10-02 18:08 UTC] sniper@php.net
There have been a lot of fixes in this code since 4.0.4pl1.
Please try the latest CVS snapshot from http://snaps.php.net/ and reopen if this problem still exists.

--Jani

 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Tue May 06 00:01:29 2025 UTC