|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2002-01-09 03:24 UTC] yohgaki@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Nov 06 05:00:01 2025 UTC |
Basically, the shmop_open function does not allow for writing to shared memory if pre-allocated memory is opened using the ACCESS (rather than CREATE) mode. This was found when using the shmop functions for fast interprocess communication between a number of php cgi scripts. The solution to this bug was to create another mode, WRITE (w) that uses IPC_R & IPC_W shm flags. To reproduce the problem:- # ** BEFORE fix modifications are made ** # ** change to php cgi directory and run server command (C) in one telnet session then run client command (A) in another. Client cannot write! echo '<? $id = shmop_open(0xff00, "c", 777, 1000); print "Server: Got ID\n"; shmop_write($id, "Hello", 0); sleep(5); $in = shmop_read($id, 0,5); print "Server: Got \"$in\" back from client!\n"; ?>' | ./php -q & echo '<? $id = shmop_open(0xff00, "a", 0,0); print "ClientA: Got ID: $id\n"; $in = shmop_read($id, 0,5); print "ClientA: Got \"$in\" from server!\n"; $bytes = shmop_write($id, $text = "aMode", 0); print "ClientA: Wrote $text to server! ($bytes bytes)\n"; sleep(12); print "\n\n"; ?>' | ./php -q # ** shmop_open in ACCESS mode does not allow writing to shared memory! # ** So, I created a WRITE ("w") mode to allow writing and left ACCESS ("a") mode as read_only. # ** AFTER fix modifications are made ** # ** change to php cgi directory and run server command (C) in one telnet session then run new client command (W) in another. Client can now write. echo '<? $id = shmop_open(0xff00, "c", 777, 1000); print "Server: Got ID\n"; shmop_write($id, "Hello", 0); sleep(5); $in = shmop_read($id, 0,5); print "Server: Got \"$in\" back from client!\n"; ?>' | ./php -q & echo '<? $id = shmop_open(0xff00, "w", 0,0); print "ClientW: Got ID: $id\n"; $in = shmop_read($id, 0,5); print "ClientW: Got \"$in\" from server!\n"; $bytes = shmop_write($id, $text = "wMode", 0); print "ClientW: Wrote $text to server! ($bytes bytes)\n"; sleep(12); print "\n\n"; ?>' | ./php -q # ** Modifications required for bug fix, include changing ext/shmop.c Existing /ext/shmop.c [shmop_open()]: /* {{{ proto int shmop_open (int key, int flags, int mode, int size) gets and attaches a shared memory segment */ PHP_FUNCTION(shmop_open) { ... if (memchr((*flags)->value.str.val, 'a', (*flags)->value.str.len)) { shmflg = SHM_RDONLY; shmop->shmflg |= IPC_EXCL; } else if (memchr((*flags)->value.str.val, 'c', (*flags)->value.str.len)) { shmop->shmflg |= IPC_CREAT; shmop->size = (*size)->value.lval; } else { php_error(E_WARNING, "shmopen: access mode invalid"); efree(shmop); RETURN_FALSE; } shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg); if (shmop->shmid == -1) { php_error(E_WARNING, "shmopen: can't get the block"); efree(shmop); RETURN_FALSE; } ... } /* }}} */ Corrected /ext/shmop.c [shmop_open()]: /* {{{ proto int shmop_open (int key, int flags, int mode, int size) gets and attaches a shared memory segment */ PHP_FUNCTION(shmop_open) { ... if (memchr((*flags)->value.str.val, 'a', (*flags)->value.str.len)) { shmflg = SHM_RDONLY; shmop->shmflg |= IPC_EXCL; } else if (memchr((*flags)->value.str.val, 'c', (*flags)->value.str.len)) { shmop->shmflg |= IPC_CREAT; shmop->size = (*size)->value.lval; } else if (memchr((*flags)->value.str.val, 'w', (*flags)->value.str.len)) { shmop->shmflg |= IPC_R; shmop->shmflg |= IPC_EXCL; shmop->shmflg |= IPC_W; } else { php_error(E_WARNING, "shmopen: access mode invalid"); efree(shmop); RETURN_FALSE; } ... } /* }}} */ # * Configuration lines for php_4.0.5.tar.gz compiling ./configure "--enable-memory-limit=yes" "--enable-sockets" "--with-openssl" "--enable-shmop" "--enable-debug=no" "--enable-xml" "--enable-ftp" "--with-config-file-path=/etc" "--with-mysql=/usr/local/" "--with-sybase=/usr/local/freetds/" "--enable-dba=yes" "--with-gdbm=/usr/local/" "--with-mhash=/usr/local/" "--with-curl=/usr/local/" "--with-zlib=/usr/local/" "--with-gd=/usr/local/" # Search/replace required for freetds implementation perl -pi -e 's/dbopen/tdsdbopen/g; s/(DBSETLCHARSET)/\/\/$1/g;' ext/sybase/php_sybase_db.c # * PHP.ini not considered relevant to this bug report.