Andres Salomon
10/13/2004 3:35:00 PM
I have some code that triggers a race somewhere in mysql. Basically, what
happens is this (all in ruby code):
1) using ruby-dbi w/ the mysql DBD, a connection is made to a database.
2) fork() is called
3) the child process redirects std{in,out,err} to /dev/null, and then runs
a SQL query; SET AUTOCOMMIT=1
4) the child process runs another SQL query; this one is an INSERT.
5) the parent process exits. This exit calls all finalizers on objects in
the parent's memory, including free_mysql() (from mysql-ruby, free_mysql
is set as a callback inside init() via Data_Make_Struct()). free_mysql()
closes the mysql connection.
6) if timed correctly, the INSERT from step 4 hangs indefinitely.
The race itself is another issue (a bug in libmysqlclient or innodb,
presumably). However, the reason why the race occurs is something that
I'd like to solve. Is there any suggestions for what I should do?
Basically, I need to force the mysql object to not be destroyed in the
parent process. Simply closing and reopening the database handle in the
child doesn't work, as there's a chance that the parent may want to do
some sql calls (and if the child closes the connection.. well, the problem
just moves there, instead).
So, I need a way to basically call undefine_finalizer for the callback
supplied to Data_Make_Struct(); or, I need a way to properly clone/dup the
mysql connection in the child, such that I destroy the original connect
to the database (that is shared w/ the parent) w/out sending a QUIT to
the mysqld, and then replace it w/ a new connection to the db.
A generic solution would be great. A persistence framework would solve
this problem for me, as well; something that allows me to open one DBI
connection, and share that amongst multiple ruby scripts and processes.
The DBI object should be reconstituted from memory/file/socket
somewhere, w/ the idea that destruction of the object is disabled (unless
a timeout occurs). A timeout should be set somewhere, so that if the DBI
connection is not used for 600 seconds or so, the object is destroyed, and
any script needing it after that has it automatically created. Does
anything like this exist? Being able to use it for other things would be
useful, as well. For example, I currently load XSL templates from
multiple files, and form an XSL object.. If I could keep this in memory,
via persistence, that would be ideal.
Note that this is being called via an interpreter inside of an apache
module; mod_ruby isn't really an option, nor would I want to add this
functionality to my apache module if I can get around it.