php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #28868 Thread safty issue with stream_wrapper_register?
Submitted: 2004-06-21 16:53 UTC Modified: 2004-06-21 23:11 UTC
From: cleong at nflc dot org Assigned: pollita
Status: Closed Package: Filesystem function related
PHP Version: 4.3.7 OS: Windows 2000
Private report: No CVE-ID:
 [2004-06-21 16:53 UTC] cleong at nflc dot org
Description:
------------
On Windows 2000, with PHP running as an Apache module, stream_wrapper_register() would fail when there are concurent scripts using that function. It would either fail without an error message or causes the Apache process to crash. When there's just one script running the function works fine. 

To reproduce this bug, open a couple browser windows and go to the reproduce code in each. 

I can get around the bug by generating a random class name and protocol name everytime (using eval for the class definition).

Reproduce code:
---------------
<?

// example class taken from manual

class VariableStream {
   var $position;
   var $varname;
   
   function stream_open($path, $mode, $options, &$opened_path) 
   {
       $url = parse_url($path);
       $this->varname = $url["host"];
       $this->position = 0;
       
       return true;
   }

   function stream_read($count) 
   {
       $ret = substr($GLOBALS[$this->varname], $this->position, $count);
       $this->position += strlen($ret);
       return $ret;
   }

   function stream_write($data) 
   {
       $left = substr($GLOBALS[$this->varname], 0, $this->position);
       $right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
       $GLOBALS[$this->varname] = $left . $data . $right;
       $this->position += strlen($data);
       return strlen($data);
   }

   function stream_tell() 
   {
       return $this->position;
   }

   function stream_eof() 
   {
       return $this->position >= strlen($GLOBALS[$this->varname]);
   }

   function stream_seek($offset, $whence) 
   {
       switch ($whence) {
           case SEEK_SET:
               if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
                     $this->position = $offset;
                     return true;
               } else {
                     return false;
               }
               break;
               
           case SEEK_CUR:
               if ($offset >= 0) {
                     $this->position += $offset;
                     return true;
               } else {
                     return false;
               }
               break;
               
           case SEEK_END:
               if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
                     $this->position = strlen($GLOBALS[$this->varname]) + $offset;
                     return true;
               } else {
                     return false;
               }
               break;
               
           default:
               return false;
       }
   }
}

stream_wrapper_register("var", "VariableStream")
   or die("Failed to register protocol");

$myvar = "";
   
$fp = fopen("var://myvar", "r+");

fwrite($fp, "line1\n");
fwrite($fp, "line2\n");
fwrite($fp, "line3\n");

rewind($fp);
while (!feof($fp)) {
   echo fgets($fp);
}

session_write_close();	// in case auto-session is on
for($i = 0; $i < 30; $i++) {
     // make the script run for 30 seconds
     sleep(1);
}

fclose($fp);
var_dump($myvar);

?>

Expected result:
----------------
Same result in each window.

Actual result:
--------------
While the first script is still running, the second script would say "Failed to register protocol". If you refresh the second window, sometimes it works, sometimes it causes a general protection error. 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-06-21 18:34 UTC] pollita@php.net
There is absolutely a thread safety issue here.  I assume you're running Apache2?

For the moment, I'd suggest Apache1 or Apache2-pre-fork.  In the mean time we'll be working on fixing this asap.
 [2004-06-21 21:40 UTC] pollita@php.net
The userwrappers part of this bug has been fixed in CVS, please try the next snapshot available from http://snaps.php.net . 

However this particular bug highlights a similar problem with userspace filters, so I'm going to leave this bugreport open while I address that side of things.  Fortunately since userspace filters are not available in PHP4, this will only require fixing in this PHP5 branch.
 [2004-06-21 23:11 UTC] pollita@php.net
Userspace filter threadsafty fixed now.  There's a potential to run into this problem again with transports should those ever be exposed to userspace, but that doesn't seem terribly likely.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 24 02:02:10 2014 UTC