ID: 10656
Updated by: yohgaki
Reported By: [EMAIL PROTECTED]
Old Status: Open
Status: Closed
Bug Type: Semaphore related
Operating System: FreeBSD 4.3 (i386)
PHP Version: 4.0.5
New Comment:

Supposed to be fixed in CVS.
Please submit bug if you find any problem.




Previous Comments:
------------------------------------------------------------------------

[2001-05-03 22:55:44] [EMAIL PROTECTED]

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.


------------------------------------------------------------------------



Edit this bug report at http://bugs.php.net/?id=10656&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