Re: [libdbi-users] Possible dbd_mysql thread unsafe problem?

2019-11-15 Thread Ethan Funk
I think I found the problem in the mysql dbd driver code.:

dbd_finalize() calls mysql_server_end(), which is deprecated in the
current mysqlclient21 library, but results in a call to a replacement
function which is intended to be called only once, at the end of a
process.  With the call being made inside dbd_finalize(), the
mysql_server_end() gets called each time my application code finished
with a libdbi instance.  Reading between the lines in the MySQL
documentation, it looks think the mysql_server_end() call to it's new
counter part frees memory which is allocated by a pthread_once()
function triggered by mysql_library_init(), which itself is called by
mysql_init() via the libdbi driver on each connection attempt.  So my
code's first libdbi connection results in the memory being allocated,
with subsequent calls in other threads being ignored.  But
dbd_finalize() gets called at the end of EVERY libdbi instance closure,
so the memory if freed over and over again.  I don't see a mechanism
for a once-per-process driver shutdown callback in libdbi, so I want to
try commenting out mysql_servefr_end() in dbd_finalize().  This will
leak memory which is never freed at the end of the process, but so
what.  It is only allocated once per process, so the operating system
process shutdown will free the memory.

Unfortunately, I can't seem to build my modified code for testing with
the libdi_dbd project code. "./configure" is giving me the following
error:
configure: error: Invalid libdbi directory - include files not found.

This is after configure has already indicated that yes, it has located
the dbi header files, which I installed with the libdbi-dev package
with the Ubuntu apt command.

How might I be able to fix this error, and proceed with testing my code
fix?

Thanks,
Ethan...

On Wed, 2019-11-13 at 14:19 -0700, Ethan Funk wrote:
> I am having a problem with libdbd_mysql on linux (Ubuntu 19.10)
> reagding thread fasety.
> There used to be two versions of libmysqlclient, one was thread safe,
> one was not. However,
> now there seems to be only one client library, which I understood was
> thread safe: libmysqlclient.so.21.
> 
> Any insight into the dump below would be greatly appreciated!
> 
> Ethan...
> 
> Here is a valgrind dump of a read-already-freed error that occurs in
> what I will call thread #3
> when it attempts to connect to MySQL.  This thread has it's own libdbi
> instance, yet mysql_real_connect
> is trying to read memory allocated by the first thread (thread #1) that
> first called mysql_real_connect, 
> after that same memory was freed by another thread (thread #2) that
> called mysql_server_end as it was 
> finishing. Each thread has it's own libdbi instance, so why is
> libmysqlclient sharring memory between 
> threads? It's looking like the libmysqlclient isn't thread safe.
> 
> ==2828== Invalid read of size 1
> ==2828==at 0x4A3A042: strlen (vg_replace_strmem.c:461)
> ==2828==by 0x141A46C1: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A5468: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A54A8: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A373E: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x4FE041E: __pthread_once_slow (pthread_once.c:116)
> ==2828==by 0x141A320D: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A41B2: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A429E: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x1415472B: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x1415492A: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141577A8: mysql_real_connect (in /usr/lib/x86_64-
> linux-gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x12F47435: dbd_connect (in /usr/lib/x86_64-linux-
> gnu/dbd/libdbdmysql.so)
> ==2828==by 0x4DC37AE: dbi_conn_connect (in /usr/lib/x86_64-linux-
> gnu/libdbi.so.1.1.0)
> ==2828==by 0x134BFA: dbSetupConnection (database.c:211)
> ==2828==by 0x1357F6: DeleteLogEntry (database.c:440)
> ==2828==by 0x131ECE: taskCallProcInThread (tasks.c:73)
> ==2828==by 0x4FD7668: start_thread (pthread_create.c:479)
> ==2828==by 0x567B322: clone (clone.S:95)
> 
> Memory was freed in a thread (lets call it thread #2) that ran and
> completed. It created it's own 
> dbi instance, did it's thing, and then closed it's MySQL connection and
> shutdown the instance.
> So why is it freeing memory deep in the mysql driver that it did not
> allocate?
> 
> ==2828==  Address 0x1343e698 is 424 bytes inside a block of size 4,088
> free'd
> ==2828==at 0x4A37F90: free (vg_replace_malloc.c:540)
> ==2828==by 0x141A9B8A: ??? (in /usr/lib/x86_64-linux-
> gnu/libmysqlclient.so.21.1.17)
> ==2828==by 0x141A8756: ??? (in /us

[libdbi-users] Possible dbd_mysql thread unsafe problem?

2019-11-13 Thread Ethan Funk
I am having a problem with libdbd_mysql on linux (Ubuntu 19.10)
reagding thread fasety.
There used to be two versions of libmysqlclient, one was thread safe,
one was not. However,
now there seems to be only one client library, which I understood was
thread safe: libmysqlclient.so.21.

Any insight into the dump below would be greatly appreciated!

Ethan...

Here is a valgrind dump of a read-already-freed error that occurs in
what I will call thread #3
when it attempts to connect to MySQL.  This thread has it's own libdbi
instance, yet mysql_real_connect
is trying to read memory allocated by the first thread (thread #1) that
first called mysql_real_connect, 
after that same memory was freed by another thread (thread #2) that
called mysql_server_end as it was 
finishing. Each thread has it's own libdbi instance, so why is
libmysqlclient sharring memory between 
threads? It's looking like the libmysqlclient isn't thread safe.

==2828== Invalid read of size 1
==2828==at 0x4A3A042: strlen (vg_replace_strmem.c:461)
==2828==by 0x141A46C1: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A5468: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A54A8: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A373E: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x4FE041E: __pthread_once_slow (pthread_once.c:116)
==2828==by 0x141A320D: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A41B2: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A429E: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1415472B: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1415492A: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141577A8: mysql_real_connect (in /usr/lib/x86_64-
linux-gnu/libmysqlclient.so.21.1.17)
==2828==by 0x12F47435: dbd_connect (in /usr/lib/x86_64-linux-
gnu/dbd/libdbdmysql.so)
==2828==by 0x4DC37AE: dbi_conn_connect (in /usr/lib/x86_64-linux-
gnu/libdbi.so.1.1.0)
==2828==by 0x134BFA: dbSetupConnection (database.c:211)
==2828==by 0x1357F6: DeleteLogEntry (database.c:440)
==2828==by 0x131ECE: taskCallProcInThread (tasks.c:73)
==2828==by 0x4FD7668: start_thread (pthread_create.c:479)
==2828==by 0x567B322: clone (clone.S:95)

Memory was freed in a thread (lets call it thread #2) that ran and
completed. It created it's own 
dbi instance, did it's thing, and then closed it's MySQL connection and
shutdown the instance.
So why is it freeing memory deep in the mysql driver that it did not
allocate?

==2828==  Address 0x1343e698 is 424 bytes inside a block of size 4,088
free'd
==2828==at 0x4A37F90: free (vg_replace_malloc.c:540)
==2828==by 0x141A9B8A: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A8756: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x14148982: mysql_server_end (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x12F4684C: dbd_finalize (in /usr/lib/x86_64-linux-
gnu/dbd/libdbdmysql.so)
==2828==by 0x4DC2E4D: dbi_shutdown_r (in /usr/lib/x86_64-linux-
gnu/libdbi.so.1.1.0)
==2828==by 0x134440: dbi_instance_free (database.c:56)
==2828==by 0x4FD6600: __nptl_deallocate_tsd.part.0
(pthread_create.c:301)
==2828==by 0x4FD7689: __nptl_deallocate_tsd (pthread_create.c:256)
==2828==by 0x4FD7689: start_thread (pthread_create.c:490)
==2828==by 0x567B322: clone (clone.S:95)

This is in the first thread in the program to make use of libdbi/MySQL,
and it is still 
running/connected to MySQL using a unique libdbi intance.

==2828==  Block was alloc'd at
==2828==at 0x4A36E96: malloc (vg_replace_malloc.c:309)
==2828==by 0x141A9A30: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A9AEB: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A4E1C: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1419CFA0: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1419D95E: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1416FD29: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A2A66: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A3771: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x4FE041E: __pthread_once_slow (pthread_once.c:116)
==2828==by 0x141A320D: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A41B2: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x141A429E: ??? (in /usr/lib/x86_64-linux-
gnu/libmysqlclient.so.21.1.17)
==2828==by 0x1415472B: ??? (in /usr/lib/x86_64-linux-
gnu/lib