Re: cannot reconcile mysql client library thread requirements with clsql code
JTK <[email protected]> Wed, 25 Apr 2012 12:14:34 -1000
| Newsgroups | gmane.lisp.clsql.general |
|---|---|
| Message-ID | <[email protected]> |
On Apr 25, 2012, at 5:22 AM, Nathan Bird wrote:
> On 04/24/2012 05:46 PM, JTK wrote:
>>>
>>
>> Thanks for the tips. Is there a reference to the the sigpipe fixes?
>
> The best I've got for you is just the IRC chatlogs: we dropped it and took a different tack when we saw that rabbit hole getting much deeper.
Thanks. I think I managed to understand the IRC thread, though it was a bit difficult to follow.
Reading this: http://dev.mysql.com/doc/refman/5.0/en/threaded-clients.html the mysql docs say:
====
To avoid aborting the program when a connection terminates, MySQL blocks SIGPIPE on the first call tomysql_library_init(), mysql_init(), or mysql_connect().
If you want to use your own SIGPIPE handler, you should first call mysql_library_init() and then install your handler.
====
So it seems that the whole signal problem could be fixed by having something like this in the clsql C
code for mysql, and calling it at the first use of connect, and never calling it again. Or calling it upon load
of the mysql back end.
/* not tested */
#include <signal.h>
/* initialize clsql, and restore old SIGPIPE handler, returning 0 on success, and 1,2,3 if failure
took place at 1) getting old signal 2) initializing mysql and 3) resetting old handler
The errno returned by sigaction (cases 1,3) or msql_library_init() (case 2) is returned in *nerror* */
int clsql_mysql_init(int *nerror)
{
struct sigaction old_sigpipe_sigaction;
/* save old SIGPIPE handler */
if (sigaction(SIGPIPE, NULL, &old_sigpipe_sigaction)) {
*nerror=errno;
return 1;
}
/* call mysql_library_init(), which changes the handler */
if (*nerror=mysql_library_init(0,NULL, NULL)) return 2;
/* and restore the old handler */
if (sigaction(SIGPIPE, &old_sigpipe_sigaction, NULL)) {
*nerror=errno;
return 3;
}
return 0;
}
And the per-thread problem could be called by having a threadwrapping macro
(with-clsql-thread ….) that will call mysql_init_thread() for the first call to
connect in this thread, and unwind-protecting a corresponding call to mysql_thread_end().
This (with-clsql-thread …) macro could also do stuff for the other back-ends too, if they need it.
And it could establish per-thread pooling, if desired, using per-thread special variables.
So unless I'm missing something, the solution is pretty simple. I'll try to get around to testing
it sometime soon.