Skip to content

Conversation

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 22, 2026

The primary motivation for this change is that this sort of functionality should reside in core and not in an extension.
The reason being is that this causes issues in regard to extension dependencies and resolution, something that prevents GH-14544.

Moreover, we might want to extend the autoloading functionality (by allowing other symbols to be autoloader or registering a class map).

@Girgias
Copy link
Member Author

Girgias commented Jan 22, 2026

@petk would doing just this allow #14544 to be merged?

@petk
Copy link
Member

petk commented Jan 22, 2026

This would make the session extension not depend on the spl, yes (meaning the https://bugs.php.net/53141 would be resolved). But the main issue there would still be present - that loop of the registered extensions isn't done optimal yet and it has issues with cyclic dependencies (extension A depends on B, and extension B depends on A).

@Girgias Girgias force-pushed the autoload-move-to-zend branch from 2e649a2 to 534f17c Compare January 22, 2026 22:48
The primary motivation for this change is that this sort of functionality should reside in core and not in an extension.
The reason being is that this causes issues in regard to extension dependencies and resolution,
something that prevents phpGH-14544.
@Girgias Girgias force-pushed the autoload-move-to-zend branch from 534f17c to 03d0260 Compare January 24, 2026 12:14
@Girgias
Copy link
Member Author

Girgias commented Jan 24, 2026

This would make the session extension not depend on the spl, yes (meaning the https://bugs.php.net/53141 would be resolved). But the main issue there would still be present - that loop of the registered extensions isn't done optimal yet and it has issues with cyclic dependencies (extension A depends on B, and extension B depends on A).

Are there any other case of cyclic dependencies? Because if not and if we can detect them and error during build/compilation, that would be a more sensible approach IMHO. As cyclic dependencies just cause a lot of pain.

@Girgias Girgias marked this pull request as ready for review January 24, 2026 12:58
@Girgias Girgias requested a review from dstogov as a code owner January 24, 2026 12:58
@petk
Copy link
Member

petk commented Jan 24, 2026

Are there any other case of cyclic dependencies? Because if not and if we can detect them and error during build/compilation, that would be a more sensible approach IMHO. As cyclic dependencies just cause a lot of pain.

Yes. Probably there are. That loop would need to be refactored somehow. Because there might be cases like this:

And I can't be sure here. When looping through a list of all enabled extensions (that is retrieved from the main/internal_functions.c and main/internal_functions_cli.c with additional ones defined from the ini directives like extension and zend_extension) there are two points what something happens:

  • first the extensions get registered somewhere
  • and then after that extensions get loaded.

And that first part is probably needed for cases as described in above linked issue (or in that session and spl hidden dependency). I can't explain this properly as I would need to go through the code in more details to better understand this issue and use proper terminology here.

Basically, what the code should ideally do is:

  • get all enabled extensions
  • sort the enabled extensions based on their dependencies defined via ZEND_MOD_REQUIRED, ZEND_MOD_OPTIONAL and ZEND_MOD_CONFLICTS.
  • and then loop over extensions, register them and load them.
  • additionally, the loop should be "smart enough" to deal with possible cyclic dependencies - either if extensions were configured incorrectly or something like that.

For example, another issue here is this: #14067

But I totally understand that doing this is difficult. So whatever you can do here, all good and I agree.

#include "zend_exceptions.h"
#include "zend_string.h"

ZEND_TLS HashTable *autoloader_class_autoload_functions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is confusing me, but I'm having a hard time figuring a better one. Maybe zend_class_autoload_functions? I think that avoiding the repetition autoloader-autoload makes it less confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future scope, but I think we should avoid using ZEND_TLS in favor of EG(), as it would make migrating a request between threads easier (at least FrankenPHP wants to do that eventually).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I don't really understand why it was in ZEND_TLS. Possibly because it was in SPL so wouldn't be able to set something in the executor globals, but that limitation no longer exists if it is in Zend.

But you are the TLS expert compared to me :)

return false;
}

ZEND_API void zend_autoload_fcc_map_to_callable_zval_map(zval *return_value) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ZEND_API void zend_autoload_fcc_map_to_callable_zval_map(zval *return_value) {
ZEND_API zend_array *zend_class_autoload_functions_as_callables(void) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I do this I seem to be hitting a GC issue if I return (zend_array*)&zend_empty_array; and then on the call site just do RETURN_ARR(zend_autoload_fcc_map_to_callable_zval_map());.

Do I need to do something special?

Comment on lines 455 to 456
/* Shutdown autoloader prior to releasing values as it may hold references to objects */
zend_autoload_shutdown();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about calling it as late as this. I think that at this point it would be unsafe to execute user code.

Currently spl_autoload_functions is destroyed in php_request_shutdown -> zend_deactivate_modules. This is before it becomes unsafe to execute PHP code, but after calling destructors. I think that it makes sense to clean autolaoders after destructors, as some of them may need to load classes. But I would call this earlier than zend_deactivate(). Maybe just after php_free_shutdown_functions()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm right. Especially as we have already released objects.

@Girgias Girgias requested a review from bukka as a code owner January 24, 2026 17:36
@Girgias Girgias requested a review from arnaud-lb January 24, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants