-
Notifications
You must be signed in to change notification settings - Fork 426
fix(worker): reset ini and session if changed during worker request #2139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Not sure if the session logic belongs in this repo. On one hand we reload the session module, which purges all sessions and handlers. On the other hand this PR would then go back in and re-instate the session handler, which feels very messy. Restoring ini entries seems more sensible o me 👍 . We'd have to consider though that restoring ini entries can have other side-effects. Say, |
I agree, but I don't see a good way to handle this on the FrankenPHP side of things, as we'd need to wait for a gc cycle before attempting this in any case. If a request increases the memory limit "temporarily" it's typically for good reason. Giving user land the option to "save state" and "reroll state" would make it a simple adjustment in worker scripts, but that's not the cleanest design. |
Actually I think it's critical to have worker requests to reset state for that kind of things to whatever it was before the first request was handled. This is the root cause of the "invalid callback" bug. |
|
I disagree. Session handling is not part of FrankenPHP specifically. I also don't think it's realistic to have "any php app written in history needs to be compatible with worker mode" as a goal. At what point do we draw the line and stop short of completely rewriting php? |
|
This issue is caused by the module reloading of the session, as it destroys handlers that have been set by the request, without removing the references to those handlers. I think it's an inconsistent behavior and should be treated as a bug. |
|
It might be a bug in the context of Symfony 5, not sure if other applications currently rely on it being flushed tough. Since the handler is a custom class, it also can have private properties, which you might not want to bleed across requests. Not sure what the ideal solution is, just saying that this is easier to do on the PHP side by just re-registering the handler. |
|
I understand it might be better from the php side. However I didn't had this issue in a symfony app. |
|
Worker scripts are usually provided by frameworks. I would prefer to keep the worker code as small and focused as possible. IMHO, we should document these cases explicitly instead of adding code specially for legacy apps. It will never be possible cover all possible leaks directly in the worker mode anyway. |
|
@dunglas I may agree on ini, but sessions should be fixed on frankenphp level. I don't think php offers a userland api to restore the session handler correctyle and it's directly caused by the reload of the module. WDYT ? |
|
I agree for sessions |
|
If we're already doing sessions, which I really see more on php's side, we must definitely do it for ini settings too. |
c8ec1ea to
eefb6bb
Compare
Can't you just re-register the handler right before |
796a00a to
358b1b6
Compare
|
@AlliBalliBaba actually that's trickier, you don't need to use the session in the request 2 to have a crash. Let's assume the following workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static void ini_snapshot_dtor(zval *zv) { | ||
| zend_string_release((zend_string *)Z_PTR_P(zv)); | ||
| } |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function name ini_snapshot_dtor is ambiguous about what it destructs. Consider renaming to frankenphp_ini_snapshot_entry_dtor to clarify that it's a destructor for individual hash table entries in the INI snapshot, and to maintain consistency with the frankenphp_ prefix used by other functions in this file.
| return; /* No user handlers to snapshot */ | ||
| } | ||
|
|
||
| worker_session_handlers_snapshot = malloc(sizeof(session_user_handlers)); |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory allocated with malloc() should be freed with free(), but other snapshot data uses Zend's memory management (ALLOC_HASHTABLE/FREE_HASHTABLE, emalloc/efree). For consistency and to ensure proper cleanup during PHP request shutdown, consider using emalloc() instead of malloc() here.
| worker_session_handlers_snapshot = malloc(sizeof(session_user_handlers)); | |
| worker_session_handlers_snapshot = emalloc(sizeof(session_user_handlers)); |
| restore_capacity = restore_capacity ? restore_capacity * 2 : 8; | ||
| entries_to_restore = erealloc(entries_to_restore, | ||
| restore_capacity * sizeof(zend_string *)); |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first call to erealloc() when entries_to_restore is NULL should use emalloc() instead, as erealloc(NULL, size) behavior may not be portable. Initialize entries_to_restore with emalloc() on the first allocation.
| restore_capacity = restore_capacity ? restore_capacity * 2 : 8; | |
| entries_to_restore = erealloc(entries_to_restore, | |
| restore_capacity * sizeof(zend_string *)); | |
| if (restore_capacity == 0) { | |
| restore_capacity = 8; | |
| entries_to_restore = | |
| emalloc(restore_capacity * sizeof(zend_string *)); | |
| } else { | |
| restore_capacity *= 2; | |
| entries_to_restore = | |
| erealloc(entries_to_restore, | |
| restore_capacity * sizeof(zend_string *)); | |
| } |
Hi there,
I was investigating the bug reported in #977 and I found that there is a lot of things that leaks between worker requests:
The current pull requests now:
This changes improves support of worker mode for legacy applications, that do nasty stuff sometimes ^^