|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76801 require()ing a file blocks writing or deleting the file
Submitted: 2018-08-27 14:47 UTC Modified: 2018-08-30 15:00 UTC
Avg. Score:4.8 ± 0.6
Reproduced:11 of 11 (100.0%)
Same Version:2 (18.2%)
Same OS:1 (9.1%)
From: Assigned:
Status: Open Package: phpdbg
PHP Version: 7.2.9 OS: Windows
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-08-27 14:47 UTC]
On Windows when requiring a file it seems phpdbg blocks writing to that same file. Same goes trying to unlink() the file

Test script:

file_put_contents(__DIR__ . '/configuration.php', 'test');

require __DIR__ . '/configuration.php';

file_put_contents(__DIR__ . '/configuration.php', 'other data');

// neither file_put_contents nor unlink work
//unlink(__DIR__ . '/configuration.php');

Expected result:
> phpdbg -qrr test.php


Actual result:
> php test.php (with file_put_contents())


> php test.php (with unlink())


> phpdbg -qrr test.php (with file_put_contents())

[PHP Warning:  file_put_contents(\path\to/configuration.php): failed to open stream: Permission denied in \path\to\test.php on line 7]

> phpdbg -qrr test.php (with unlink())

[PHP Warning:  unlink(\path\to/configuration.php): Resource temporarily unavailable in \path\to\test.php on line 9]


release-file-handle (last revision 2018-08-28 12:55 UTC by

Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2018-08-28 11:12 UTC] sjon at hortensius dot net
FYI: This is a well known issue with windows in general (not PHP specific) and is  explained here:

> Windows inherits the semantics of share-access controls from the MS-DOS system, where sharing was introduced in MS–DOS 3.3. Thus, an application must explicitly allow sharing; otherwise an application has exclusive read, write, and delete access to the file (other types of access, such as those to retrieve the attributes of a file are allowed.)
 [2018-08-28 12:55 UTC]
The following patch has been added/updated:

Patch Name: release-file-handle
Revision:   1535460904
 [2018-08-28 12:55 UTC]
> This is a well known issue with windows in general […]

Yes.  However, the CLI SAPI closes the file handle after
inclusion, but the phpdbg SAPI does not, which may not be
intended.  A comment on phpdbg_compile_file()[1] states that the
file handler[sic] is supposed to be freed by original
compile_file() or the caller. The caller is
phpdbg_init_compile_file()[2] in this case which replaces
zend_compile_file[3], so likely phpdbg_init_compile_file() should
release the file handle.  The attached patch “release-file-handle”
would do this.

[1] <>
[2] <>
[3] <>
 [2018-08-29 11:59 UTC]
No, the caller is the caller calling zend_compile_file().

Compare with the Zend compile_file() implementation, which doesn't destroy the handle either

Effectively in phpdbg is just mirroring the behavior of compile_filename()

However, the change in might be fine, where we create our own file handle thus we must close that properly as well.

So change that patch to just call zend_destroy_file_handle() as well inside phpdbg_compile_file() (but not the init).
 [2018-08-29 14:41 UTC]
> So change that patch to just call zend_destroy_file_handle() as
> well inside phpdbg_compile_file() (but not the init).

That wouldn't fix the issue, though.
 [2018-08-30 06:03 UTC]
Then I'm seriously confused, as phpdbg_init_compile_file() does exactly the same thing as compile_file() does - what am I missing?
 [2018-08-30 15:00 UTC]
It seems that under the CLI SAPI for the included file
compile_filename()[1] is called, but not under the phpdbg SAPI.
compile_filename() calls zend_destroy_file_hande()[2] after having
called zend_compile_file(). I have checked this on Windows only,
but I guess the calls are the same on Linux.

[1] <>
[2] <>
 [2018-09-17 00:25 UTC] andrew at nicols dot co dot uk
I've just tried your patch cmb and it is indeed freeing up files now, but I'm also seeing files loaded twice in a require_once with this patch.

I haven't been able to replicate it outside of phpunit yet with a simple testcase. This wasn't happening before I applied the patch.
 [2018-09-17 04:05 UTC] andrew at nicols dot co dot uk
The attached patch fails with the following test:



echo __FILE__ . " was included\n";
 [2018-09-17 04:11 UTC] andrew at nicols dot co dot uk
Sorry, to confirm the previous comment relates to the patch suggested by

Calling a.php via php directly:
2054 nicols@boysenberry:~/git/tmp> php a.php
/Users/nicols/git/tmp/b.php was included

Calling it via phpdbg -qqr:
2055 nicols@boysenberry:~/git/tmp> phpdbg -qqr a.php
/Users/nicols/git/tmp/b.php was included
/Users/nicols/git/tmp/b.php was included
[Script ended normally]

Essentially it appears that when called via PHP CLI, a file included via require or include is not subsequently loaded if called via require_once or include_once.
However if it is called via phpdbg, it is included again.
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Feb 23 12:01:25 2019 UTC