php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79956 include_once ignores preloading
Submitted: 2020-08-11 21:09 UTC Modified: 2020-08-12 07:56 UTC
From: crell@php.net Assigned:
Status: Open Package: opcache
PHP Version: 7.4.9 OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: crell@php.net
New email:
PHP Version: OS:

 

 [2020-08-11 21:09 UTC] crell@php.net
Description:
------------
The list of include/require_once()'ed files seems to not persist between preloading and regular code run.

Given the 3 files in the test script section, if I run the following:

php -d opcache.preload=preload.php -S localhost:8080

And then view the page in a browser, I would expect to just see "A" in the output.  Instead, I see:

Including A
A

Indicating the file is really getting executed twice; once in preload, once in the page request.  However, there's no error about the function already being defined.

The "Including A" line is shown on the console when the server starts, indicating it is preloading the file.  If I remove the require_once() from index.php, the code still runs, confirming it is getting preloaded.

I don't entirely understand how that combination of results can happen, as it implies the file is being executed twice but not dying on the already-declared function.

Test script:
---------------
<?php
# a.php

print "Including A" . PHP_EOL;

function a() {
  print "A" . PHP_EOL;
}
?>

<?php
# preload.php

require_once('a.php');
?>

<?php
# index.php

header('content-type: text/plain');

require_once('a.php');

a();
?>

Expected result:
----------------
The behavior I would expect is that a file require_once()ed in preload would get skipped entirely if require_once()ed again in the main application.  That way, I'd be able to have my application require_once() all of the non-autoloadable files it needs, but then still toss all of that into preloading for production and have it just "get faster."  Whatever is happening in those files should only happen the one time, period.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-08-12 07:56 UTC] nikic@php.net
A complication here is probably that preloading cannot load everything. If you require_once'd file contains constant definitions, you'd still want those to be executed during the request.

> I don't entirely understand how that combination of results can happen, as it implies the file is being executed twice but not dying on the already-declared function.

Preloading removes the parts of the code that it successfully preloaded.
 [2020-08-17 21:54 UTC] crell@php.net
That is indeed a complicating factor.  I'll note that in the docs.

Still, this behavior of require_once() seems incorrect.  I guess we have a choice:

1) _once() doesn't mean once for preloading, but blindly including files with constants still works.  (No idea what the performance impact is here.)

2) _once() works, but caveat emptor if there are constants defined. If there are, you need to use require() instead.

I'm not sure which I favor.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC