Skip to content

Feature request #78555 - Add the option to disable dblink cleanup #8697

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

eriklundin
Copy link
Contributor

When building daemon processes with php that requires the parent process to create a persistent database connection. The cleanup of the child process closes the parents database connection. A way to disable this cleanup on a object basis would make php better for daemon projects. This problem applies to other file descriptors as-well but the most problematic is the mysqli dblink resource.

Feature request url: https://bugs.php.net/bug.php?id=78555

Updated to match master branch (php 8.2+) as requested on old PR: #4712

@eriklundin eriklundin changed the title Add the option to disable dblink cleanup Feature request #78555 - Add the option to disable dblink cleanup Jun 3, 2022
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

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

Thanks for the update!

On a quick glance, this looks mostly good to me, but maybe @kamil-tekiela would like to review.

}
MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
mysql->disable_cleanup = enable;
RETURN_TRUE;
Copy link
Member

Choose a reason for hiding this comment

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

It seems to me that a void function would make more sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would agree. I looked at the mysqli_debug() function which returned a bool and made it similar:

https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_api.c#L371

Co-authored-by: Christoph M. Becker <[email protected]>
@kamil-tekiela
Copy link
Member

I don't like this. I am not sure how exactly this function is meant to be used. Can you provide some tests?

Isn't there a better way to do this? Maybe a persistent connection would be suitable for this use case? What is special about mysqli that it needs such workaround? Don't other objects/extensions exhibit the same behaviour? TBH I am unclear what issue this function is trying to solve.

@eriklundin
Copy link
Contributor Author

There are examples in https://bugs.php.net/bug.php?id=78555

In short. The problem is that PHP automatically runs mysql_close() on the MYSQLI resource when the object is destroyed which causes the mysql-server to flag the connection as closed. When working with forking this is huge problem.

If you start a process and initiate a mysql connection. Then later fork the process, the child process will inherit the connection and when the child dies it runs mysql_close() on the socket. This will brick the connection from the parent process with "MySQL Server has gone away".

When for example you would write a similar program in C you have the option to not mysql_close() the connection from the child but in php the dtor automatically runs this even if don't want it to. So my feature request is a simple option to disable this so that forking is made easier without a lot of messy workarounds.

@eriklundin
Copy link
Contributor Author

On a side note. SSL-sockets suffer the same issues in PHP. The SSL-connection will be ended from the child process which bricks it for the parent process.

I've made a separate extension to address this issue:
https://github.com/eriklundin/php-rawnet

This extension is used in production environments and serving thousands of connections. But since the mysqli extension just requires minor changes it would be much better if it just had the option to disable cleanup.

@kamil-tekiela
Copy link
Member

What about PDO? What about pgsql? What about all the other database extensions currently bundled with PHP? Don't they have the same issue?

@eriklundin
Copy link
Contributor Author

They probably have the same issue. But I almost exclusively use MySQL both private and professionally. Getting this fixed for at least the MySQL extension would be better then not having it at all? Maybe it would be in someone's interest to fix the others if the need exists outside of MySQL?

@kamil-tekiela
Copy link
Member

I am rather against it. The mysqli extension is used less and less. Most contemporary projects are using PDO nowadays. If a solution is needed then I would imagine PDO should receive it first and foremost. But I think that the problem you are describing needs an entirely different approach, one that doesn't potentially create dangerous situations in extensions. Adding a new function to the mysqli extension seems counter-productive to me. Whoever is still using the mysqli extension will be left wondering what the actual purpose of this new function is and I can guarantee you that it will be abused. The goal is to make this old extension easier to use rather than complicate it more.

I think this PR should be rejected. It tries to fix a very niche problem in a way that is potentially dangerous to many other users. I encourage you to find a more generic solution to the problem. It would probably be a good idea to email the mailing list and start a discussion on how this problem could be tackled in a better way. Maybe someone already has done this before?

@eriklundin
Copy link
Contributor Author

If you do nothing the result is exactly the same as now. The connection will be broken through the socket when the object is destroyed or the process dies. So you have to make an active choice to enable this feature on each object. I can't see how this can be abused? There's a lot of easier ways to crash a server or open up security issues with just standard functions like file_put_contents() etc.

In linux at least the kernel will clean up open file descriptors/sockets when the process is ended. So even if PHP wouldn't fclose() the socket it will be closed either way. It's just that the developer gets the choice on if the "break up" message over the socket should be sent or not.

We use the mysqli functions on a massive scale. We have our own version of PHP built with this patch applied. Without it, writing services that use MySQL connections and forking would be horrendous. I would rather see it applied upstream then having to port it for each new php version.

I wouldn't see system services written in php as niche. But if proposals to improve PHP towards this usage is rejected it certainly will be less and less used.

@cmb69
Copy link
Member

cmb69 commented Jun 7, 2022

@eriklundin, IMO, we should provide some mitigation (if there is no proper solution), but I understand @kamil-tekiela's concerns. I think it's best to discuss this on the internals mailing list. AFAIK, you're already subscribed, so please send a message there.

@eriklundin eriklundin requested a review from kocsismate as a code owner October 7, 2023 13:51
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.

4 participants