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.