From:             [EMAIL PROTECTED]
Operating system: Red Hat
PHP version:      4.0.4pl1
PHP Bug Type:     *Session related
Bug description:  Nasty bug in mod_mm.c causes CGI POST to stop working

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;


-- 
Edit Bug report at: http://bugs.php.net/?id=9639&edit=1



-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to