The Bugureaucracy

October 11th, 2020

Hot on the heels of having solved that gnarly compilation trouble, I ended up taking a walk through the byzantine labyrinth of bugs that may - or may not! - cause libmysqlclient1 to be effectively single-connection, whatever other claims and pretense may be put forward anywhere - and yes, I know that such claims are made and such pretense is and will be hotly supported. Nevertheless, the fact that libmysqlclient's connect method (mysql_real_connect) simply hangs randomly and unrecoverably2 means exactly, precisely and inescapably that libmysqlclient provides at most one connection to a MySQL server and nothing else. And if you itch to tell me all about how my environment is "wrong" because "should have" used this not that and "upgraded" and so on, better shut up and read some more around - who knows, you might even arrive then some day to actually have something of your own to say instead of pushing and peddling without even realising it the precise problems that weigh you down currently.

The above unsavoury discovery of libmysqlclient's limitation came about in the usual way this sort of things do: by surprise and at a slight change of the environment otherwise. I took about one week to implement -with suspiciously little trouble- a fully working set of Ada bindings for MySQL to finally ditch the awkward and time-consuming dance back and forth Ada-C-Ada for each and every query that the server needs to do. And then I took a deep dive in madness as the code that worked perfectly fine in one environment started simply hanging randomly as soon as deployed on the actual working server and with a rather weird stack trace and error - all of a sudden, since the... latin1 charset was supposedly not found despite obviously being both installed and previously found! Isolating the call and retrying proved entirely futile too: no, libmysqlclient and the whole stack of chairs that's supposedly a working environment is utterly unable to recover, no matter how much time or retries you are willing to spend on it. Whoever heard of recovering from errors, right?

At any rate, I started then reading around to see otherwise if I can perhaps find the actual source of such trouble and maybe even - such strange idea - fix it in a way that is for once slightly easier than making my own libmysqlclient-equivalent too. Well, sources of trouble I found for sure, even more and more interesting than I had hoped for. For starters, the hanging behaviour is confirmed to happen sometimes indeed but you get your pick and choose - hey, you wanted the freedom to choose, right? - as to what exactly causes it in any specific observed case! For instance, searching through MySQL bugs leads one to #22322504 and #79510 that would perhaps fit the bill since they have to do with mysql_real_connect being in fact not thread-safe when invoked with some default options. Except, at a closer look, it turns out that those bugs (yes, it's not just one, never just one, bugs come in sets and bunches at this level, basically it's organised bugs ftw) are supposedly *fixed* in MySQL 5.7.14, while my environment is running MySQL 5.7.28. Sure, they might have reintroduced one or both or a combination or something else entirely in between those two versions - do you want to spend your time checking and tracking that?

Or perhaps if you choose to just believe that release document of MySQL and therefore assume that the problem is a different one, how about following the trail of that weird complaint about the latin1 character set? That one leads apparently to a very original set of bugs reported though, it would seem, mainly on freebsd lists starting with a bug in... libc, since libc provides a stub pthread_once method to "help" when you don't actually need to link in the pthreads library: the way it helps, is that it makes therefore *sure* that you DO have to link the pthreads library or your program will crash since the stub does not do the initializations that it's supposed to do. There's at least one MySQL bug report dismissed though as not a MySQL bug so let's quote instead from where someone actually looked at some code instead of dismissing the problem as "not my fault":

libc.so defines a "stub" version of pthread_once(). Unfortunately, the stub version simply returns zero (success) without ever calling the init function, which does not satisfy the contract of pthread_once.

The effect of this is that if code which uses pthread_once is accidentally linked without libpthread, the code's attempts to initialize data structures using pthread_once will silently fail, probably leading to unexpected and hard-to-debug crashes or other problems. When debugging this code, the developer may figure out easily enough that pthread_once() is not functioning, but is unlikely to realize that this is because he has not linked against libpthread -- most developers would expect to have seen a linker error if this were the problem.

Do you enjoy the helpful way libc helps you yet? Wait, it gets even better though: further down the line, there's also libstdc++ that decided to *rely* on this faulty behaviour of libc3 so that now fixing one breaks the other and therefore you are neatly caught in the classic bureaucratic manner - you have plenty of options and none of them solves anything but they can surely keep you busy and bouncing from one to the other forever. You wanted "freedom to choose" and they serve you exactly that - in name, of course but isn't that exactly how you "deliver" on your word and with your tasks, too? So, enjoy it, I guess.

Perhaps you noticed in the links above that they are on freebsd lists so now the additional question thus gained is - does the specific libc on my machine have the faulty or the correct stub? Sure, I can write some code and test it, as one option. Or I can dig out the code and read to find out, as another option. Both though are "options" to spend my time on something with dubious return at best. Isn't this a wonderful world when the attempt to solve one problem which shouldn't have been there to start with simply results in increasingly more and more complex trouble that - just the same! - shouldn't have been there in the first place at all? Well, if you are the sort who wants to actually expose and solve problems as opposed to making do and hiding them but otherwise doesn't quite stop to pick and choose the problems worth solving, then all and any bureaucracies will always be happy of course to provide you with as deep a set of nonsensical problems as you require to never get to do anything useful anyway!

As for myself, by the time I read all about that stub and the rest, I stopped wasting my time digging any further. Instead, I got back to my Ada bindings for MySQL and added to its functionality so that it can provide thread-safe access to a single connection since that's all that it is actually available currently. It took all of half a day, too and it will serve *me* a lot in the future as well although indeed, I don't expect it will serve libmysqlclient in any way. Did you ever stop to really and fully consider just who exactly does your work, whatever that might be, actually - as opposed to seemingly - benefit?


  1. I can give specific "version numbers", sure, here you go: 20.3.15 for libmysqlclient and 5.7.28 for mysql. Do you think those are *exactly* the same on any OS and moreover do you think that nothing else comes into play when you try to actually use them? If you do, then the more fool you but don't let me spoil it for you - go forth and waste in that labyrinth as much time and life as you want, I don't even want to stop you, why would I? 

  2. If reliably, as well, since all it takes is enough calls to it, for varying definitions of enough in this context. 

  3. Here's the reason as given: "Revert the previous change to pthread_once() stub in libc. It is actually a feature that libstdc++ depends on to simulate the behavior of libc's internal '__isthreaded' variable. One benefit of this is that _libc_once() is now private to _once_stub.c." The classic "it's not a bug but a feature! Why and how come? Because... I find it more convenient like that!