Skip to content
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

Ensure MySQL is only initialized once #465

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

roavin
Copy link

@roavin roavin commented Feb 9, 2025

See #464

Note that this introduces a pthreads dependency; I don't know if this requires further changes to Makefile.PL.

@Grinnz
Copy link
Contributor

Grinnz commented Feb 9, 2025

Pardon my ignorance on the issue, but will this work on perls build without pthreads? (On recent perls, this now has to be explicitly requested, but it was the default on very old perls)

@Grinnz
Copy link
Contributor

Grinnz commented Feb 9, 2025

Here's an example of a check for whether a Perl has been compiled with pthreads: https://metacpan.org/release/OLEG/Net-DNS-Native-0.22/source/Makefile.PL

I do not suggest requiring pthreads as this module does, because it's not central to DBD::mysql's operation. But perhaps this code needs to be conditional on it somehow

@roavin
Copy link
Author

roavin commented Feb 9, 2025

It's certainly possible to do this without pthreads; perhaps the perl runtime or MySQL client library ship with synchronization primitives that could be used but I personally am not familiar enough with them to know if that is the case or not. I used pthreads here because it provided the necessary facility and is, as far as I'm aware, fairly universally available.

@dveeden
Copy link
Collaborator

dveeden commented Feb 10, 2025

Maybe using BOOT would be sufficient?

diff --git a/dbdimp.c b/dbdimp.c
index 39db033..dff796e 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -1206,7 +1206,6 @@ MYSQL *mysql_dr_connect(
 #else
     client_flag = CLIENT_FOUND_ROWS;
 #endif
-    mysql_library_init(0, NULL, NULL);
     mysql_init(sock);
 
     if (imp_dbh)
diff --git a/mysql.xs b/mysql.xs
index 6017ed2..ca014b0 100644
--- a/mysql.xs
+++ b/mysql.xs
@@ -31,6 +31,9 @@ INCLUDE: mysql.xsi
 
 MODULE = DBD::mysql    PACKAGE = DBD::mysql
 
+BOOT:
+mysql_library_init(0, NULL, NULL);
+
 double
 constant(name, arg)
     char* name

@roavin
Copy link
Author

roavin commented Feb 10, 2025

Maybe using BOOT would be sufficient?

Probably not - since each MPM worker thread spawns its own Perl interpreter, BOOT would possibly be executed simultaneously as well (actually, it might make the bug quicker to trigger since it no longer depends on requests that connect to the DB, which could be a benefit in its own way 🙃 )

It looks like neither Perl's XS interface nor libmysql export any synchronization primitive that can be used here, which is unfortunate.

How likely is the situation that somebody uses DBD::mysql with a Perl or system that doesn't have pthreads? Would it be reasonable to add the check (which makes the build fail without pthreads) as suggested above by @Grinnz ?

@Grinnz
Copy link
Contributor

Grinnz commented Feb 10, 2025

It is quite likely on Perls older than 5.20 that DBD::mysql would be used on a Perl without pthreads linked. I don't think it's a good idea to break this configuration.

@Grinnz
Copy link
Contributor

Grinnz commented Feb 10, 2025

I also am not familiar with how pthreads works on Windows, as you can see in the module I linked there is some special casing around that.

@roavin
Copy link
Author

roavin commented Feb 10, 2025

It is quite likely on Perls older than 5.20 that DBD::mysql would be used on a Perl without pthreads linked. I don't think it's a good idea to break this configuration.

5.20 is over 10 years old now, though. How likely is it to have such an old Perl version with such a new version of DBD::mysql?

I also am not familiar with how pthreads works on Windows, as you can see in the module I linked there is some special casing around that.

pthreads isn't shipped with Windows directly, unlike on Linux where pthreads is pretty much always available when a compiler is available. The module you linked includes the prebuilt lib files for Windows, which is why it has the special case. For something like pthreads, that's probably the simplest working approach that doesn't introduce other additional dependencies.

@dveeden
Copy link
Collaborator

dveeden commented Feb 10, 2025

For now it looks like:

  • Some ifdef magic might be needed to make this work on installations without threading
  • Check if there is anything in Perl that abstracts threads etc.

This seems somewhat similar: https://stackoverflow.com/a/39136689/958681

Note that DBD::mysql on Windows is currently unfortunately mostly not working due to how Perl, MySQL and OpenSSL are build and shipped. However we shouldn't make that even more difficult if we can avoid it.

@roavin
Copy link
Author

roavin commented Feb 10, 2025

I can add an ifdef'd Win32 path that doesn't use pthreads, and otherwise make it spit out a warning without pthreads but still compile.

@roavin
Copy link
Author

roavin commented Feb 11, 2025

The Win32 path I described above would use the InitOnceExecuteOnce API, which pretty much does the same thing as pthread_once. That function is available starting with Windows Vista or Windows Server 2008, which are both long out of support (2017 and 2020, respectively). I presume that this won't be an issue, particularly if Windows support is wonky anyway.

I do need to set up a build environment for this, though; Windows programming is my "home territory" for work, but not for the Perl work I do in my free time. I assume it won't be particularly difficult.

@dveeden
Copy link
Collaborator

dveeden commented Feb 11, 2025

@roavin Please see this comment and the rest of that thread for the current state on Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants