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]