On Thursday 20 December 2012 10:40:32 Stas Malyshev wrote:
> Hi!
> 
> > <?php
> > if ($argv[1] > 0) {
> > 
> >    while ($argv[1]--) file_put_contents('test.tpl', "<?php
> > 
> > #".str_repeat('A', mt_rand(4000, 5000))." ?>\n", LOCK_EX);
> > } else {
> > 
> >    $p2 = popen("sapi/cli/php -n test3.php 100", "r");
> >    while (1) include 'test.tpl';
> > 
> > }
> > ?>
> 
> Yes, I can now reproduce this on my machine too. Not sure what I did
> wrong last time, but now I get bus error. I suspect there's some race
> condition between mmap and rewriting the file that creates the problem.
> The error seems to happen at offset exactly 0x1000 from the start of the
> map, which leads me to thinking that maybe the problem is that the page
> needs to be loaded, but since the file is not there, being overwritten,
> it can not be loaded anymore.

Is include supposed to take a LOCK_EX somehow? I can neither see that in php-
src (5.4.9) nor APC-trunk, doing a cursory grepping.

 APC takes a LOCK_EX in exactly one place, apc_bin_dumpfile(), which does not 
look to me like it's related to "include". The usage there is fishy anyway, 
not exactly sure, but I think the open that happens before taking LOCK_EX, 
will have truncated the file already, leading to the same type of problem as 
discussed above wrt concurrent readers.

The only chance to get the above piece of code to work reliably in theory, 
would be for the "include" to take a LOCK_EX before looking at anything 
related to the file structure, including the stat call that determines how 
much to mmap.

The prudent approach, which should avoid the problem altogether and not need 
any LOCK_EX, dictates to ALWAYS write a temporary file (new inode), then 
rename it when the write completely succeeds. Otherwise any reader, like 
"include", runs the chance of seeing a partially written file, and even 
without include using mmap internally, syntax errors would happen from time to 
time.

So, my conclusion would be that it is the code snippet above, and not any part 
of PHP or the kernel, that is at fault.

best regards
  Patrick

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to