1

I have been looking for this issue on the internet, but can't find a solution. What I'm trying to achieve is to build a CGI-application with both dependencies of OpenSSL and MySQLClient.

When I compile my program, with the following command:

g++ -Wall -o test.cgi test.cpp -I/usr/include/mysql -lcgicc -lmysqlcppconn -lmysqlclient -lcurl -lnghttp2 -lssl -lcrypto -lpthread -ldl -DCURL_STATICLIB -std=c++11 -lz -static

I get the following error:

//usr/local/lib/libcrypto.a(err.o): In function `ERR_remove_thread_state':
err.c:(.text+0xe40): multiple definition of `ERR_remove_thread_state'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libmysqlclient.a(ssl.cpp.o):(.text+0x1df0): first defined here

I have tried multiple solutions, such as both down- and upgrade to other versions of OpenSSL, as opposed here. However, I still get this error when compiling with any of the following OpenSSL versions:

  • OpenSSL 0.9.8
  • OpenSSL 1.1.0g
  • OpenSSL 1.1.1

What should I do to overcome this error and be able to compile my program statically?

TVA van Hesteren
  • 1,031
  • 3
  • 20
  • 47

1 Answers1

0

I looks like you are using an older MySQL (i.e., earlier than version 8).

In the earlier version, there is indeed a file ssl.cpp which defines ERR_remove_thread_state

void ERR_remove_thread_state(const void *)
{
    GetErrors().Remove();
}

So, two approaches you can explore. (1) Try to upgrade to a more recent version of MySQL. or (2) build your own version of MySQL using the version as installed on you system, but rename this function to something else (i.e. edit the source code of MySQL before building it).

Update: a 3rd approach to attempt -- definitely in the realm of 'hacking' -- is to modify the libmysqlclient.a to remove the offending symbol. This may or may-not work, but is fairly straight-forward to try.

To do this you need to take a copy of the libmysqlclient.a and then unpack it (ar -x). You should find an object file named ssl.cpp.o. You can then list the symbols in that file (e.g., use something like readelf -s), and confirm the ERR_remove_thread_state is found. Then strip that symbol from that file (e.g. strip -N ERR_remove_thread_state ssl.cpp.o), and then reassemble the object files back into the archive. Finally link statically to that modified archive, rather than the system one. Some caveats: because these are C++ files, you might need to use name demangling; and I've not tried this myself so unsure what consequences would be -- you would need to seriously test your application. The hope is that this symbol was not being used by any code paths, so removing it will allow successful compilation and application behaviour.

Darren Smith
  • 2,261
  • 16
  • 16
  • Hi Darren, many thanks for your reply! Alright. However, I have installed MySQL through the commands `apt-get install libmysqlcppconn-dev` and `apt-get install libmysqlclient-dev`. I though this should install the latest version. Could you tell me how I can install the most recent version of MySQL? Or could you elaborate on how to build MySQL? I'm not that familiar with building manually. I found good and clear documentation to build OpenSSL, however as already stated. Those builds to both up- and downgrade OpenSSL did not resolve the error – TVA van Hesteren Sep 17 '19 at 12:13
  • your package manager can provide you with the version of libmysqlclient that has been installed; I would be interested to see if it is indeed a version earlier that version 8. To build libmysqlclient manually, you will likely need to download the MySql source code, and refer to its build instructions. Either attempt to build the entire MySql project, or, just the client library part. Normally this is fairly straight-forwards, sometimes can be tricky. You could try rebuilding OpenSSL (after renaming ERR_remove_thread_state), although I think it is safer to rebuild the libmysqlclient. – Darren Smith Sep 17 '19 at 15:51
  • The MySQL Client version is: 5.7.27-0ubuntu0.16.04.1 I would like to try to build MySQL myself. Could you help me to build it from source? I have no idea how to build it with all possible options etc? What files should I rename, etc? Many thanks! – TVA van Hesteren Sep 17 '19 at 17:25
  • I have tried your update (3rd approach) by replacing the symbol in the `ssl.cpp.o`-file. This removes the error, but I think the modification leads to the following error: `/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libmysqlclient.a(yassl_int.cpp.o): In function 'default_password_callback': (.text+0x100): undefined reference to 'yassl_mysql_get_tty_password_ext'` – TVA van Hesteren Sep 17 '19 at 17:52
  • but, if you are statically linking to this modified libmysqlclient.a, why is the above erro referring to the system libmysqlclient.a ? I would expect your modified libmysqlclient.a to live under a temporary or user directory. – Darren Smith Sep 17 '19 at 18:57
  • on the final .a you have created, run this command to check the symbol `yassl_mysql_get_tty_password_ext` is defined: `nm -PACg libmysqlclient.a | grep yassl_mysql_get_tty_password_ext` – Darren Smith Sep 17 '19 at 19:05
  • I will do that tomorrow and get back to you. To quickly test it, i had placed the New a file on the system location and back-uped the original one. It will probably not be defined right? If it is, what should I do? And if it is defined? – TVA van Hesteren Sep 17 '19 at 21:09
  • It's best not to alter the system files, so after this experiment concludes, try to put the original file back. I expect the symbol will actually be defined. If that is the case, leads the question why it wasn't found. It's possible the order of the `.o` object files in the archive are playing an effect; you should look to try chaning the order of `yassl_int.cpp.o` and `get_password.c.o` in the archive, – Darren Smith Sep 17 '19 at 22:07
  • Darren, thanks again for your reply. I have restored the original system file. I Will try to change the file again and keep an eye on the file order on rebuilding the archive. I had just archived all files back into the archive without any specific order. I will get back to you when I have tried your solution. (Since I shouldn’t modify the system files, where should I store this one file and how can I specify the file while compiling?). Many thanks – TVA van Hesteren Sep 18 '19 at 04:57
  • Darren, the response to your `nm ....` command is: `libmysqlclient.a[get_password.c.o]: yassl_mysql_get_tty_password_ext T 0000000000000020 000000000000006c libmysqlclient.a[yassl_int.cpp.o]: yassl_mysql_get_tty_password_ext U nm: thr_cond.c.o: no symbols` This is the response when the `nm` command is executed on the `original` archive file `libmysqlclient.a` – TVA van Hesteren Sep 18 '19 at 06:21
  • you can place the modified library anyway, eg. `/opt/mysql-5.7.27/lib` ... and to link to it, use the -L option during compile, `-L /opt/mysql-5.7.27/lib` – Darren Smith Sep 18 '19 at 06:22
  • Alright thanks, what should I do in regards of the response on the `nm` command on the `original` archive file? – TVA van Hesteren Sep 18 '19 at 06:23
  • it tells us the `yassl_mysql_get_tty_password_ext` is defined inside the archive (as I suspected) – Darren Smith Sep 18 '19 at 06:24
  • Alright. I have saved the order of files in the archive by using the command `ar t libmysqlclient.a`. I have saved this response in a `txt` file. Is there a simple command to use this `txt` file as import option for the order of files to include in the archive? If I have to do this manually, it costs a lot of time and I might make an error? I can't find it on the internet. Can I use `ar r libmsyqlclient.a ssl.cpp.o` to replace the `ssl.cpp.o` file within the archive? – TVA van Hesteren Sep 18 '19 at 06:26
  • I would jjust type out the list of files into the `ar` command , file1, file2, file3, etc – Darren Smith Sep 18 '19 at 06:41
  • Darren, I have used the `ar r libmysqlclient.a ssl.cpp.o` command and it rebuilded the archive by changing the ssl.cpp.o file. Now my application compiles `statically`! HOWEVER, it returns me a `SIGSEGV` (I guess when I want to connect to the MySQL database. Can't debug that quickly at the moment. I will look into this tonight. Do you have any thoughts about this?) – TVA van Hesteren Sep 18 '19 at 06:45
  • well, I wouldn't have removed the ssl.cpp.o file entirely; aim was just to remove 1 symbol. But see, it does show inherent danger of this approach ... can lead to unxpected core dump. – Darren Smith Sep 18 '19 at 07:09
  • Darren, I have not removed the ssl.cpp.o. I have stripped the symbol and replaced the ssl.cpp.o file in the archive with the new ssl.cpp.o file without the symbol. But, if this is not going to work, can we then build MySQL 8 from source? – TVA van Hesteren Sep 18 '19 at 07:11
  • Darren, I have debugged the issue more and I foudn out that the `SIGSERV` originates from `CURL`. When I make my first `CURL`-request, it throws `SIGSERV`. During compiling, I get the 4 warnings, all about `glibc`. An example of the warning: `//usr/local/lib/libcrypto.a(dso_dlfcn.o): In function 'dlfcn_globallookup': dso_dlfcn.c:(.text+0x11): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking`. Both these warnings originate from `libcrypto` and `libcurl` – TVA van Hesteren Sep 18 '19 at 07:32
  • Darren, I have changed the flag `-static` to the flag `-static-libgcc` and the client side compiles without warnings and works on my test machines! Many thanks. I will chek whether the server-side applications will compile as well but I can't test that right now. I will come back on that and let you know. Again, many thanks you helped me alot – TVA van Hesteren Sep 18 '19 at 07:42
  • Hmm, some strange problems. This afternoon, it worked fine as I told. However I can't build it statically anymore now? I doubt if I had it statically at all. Though, it doesn't work on my test machines anymore? I use the `-static-libgcc` option as discussed. It returns no warnings and compiles, but it is still a dynamic executable at the end? – TVA van Hesteren Sep 18 '19 at 19:02
  • hmm ... you really need to have a consistent build, before you can test out these hacky approaches. You now, the other approach of just rebuilding MySql (or, upgrading to version 8), is probably better. – Darren Smith Sep 18 '19 at 21:48
  • Hi Darren, I think your 'fix' is working. Though, I have some problems with static linking the gcc compiler. I use `-static-libgcc`, but the code is not compiling as static. I read on the internet that this is common, because `glibc` is not used to be linked statically. In fact, they claim that it's better to keep `glibc` linked dynamically for better portability. However, the problem is I then would like to link all other libraries statically, which works without errors now. Though, I can't compile a working executable with dynamic `glibc` to run on other machines then compile env.How can I? – TVA van Hesteren Sep 19 '19 at 06:22
  • Darren, I have pinpointed the problem further. It seems that uploading the CGI to my other machine breaks the headers. For instance, on the compile environment, `readelf -l program.cgi` returns the right response. However, on the other machine, it returns many `unknown` and errors complaining about inconsistent headers. So, it seems that the headers get broken by uploading to the FTP-server? When I upload the same file back to the compile environment, I have no problem. So, it seems to be a problem on the deployment machine? Do you have any ideas? – TVA van Hesteren Sep 19 '19 at 07:26