There is a particularly nasty crash scenario invloving the 
garbage collector. The problem is that the dbi free routine
calls the dbi close routine, which tries to alloc new SCM
nodes. This is bad, because one should not alloc while 
the garbage collector is running. So add a flag, incidating
that a free is in progress. 

The DBD layers will have to honour this flag.

(also fixes one more mem leak).

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>

---
 include/guile-dbi/guile-dbi.h |    1 +
 src/guile-dbi.c               |   14 ++++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

Index: guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h
===================================================================
--- guile-dbi-2.0.0.orig/include/guile-dbi/guile-dbi.h  2008-09-16 
21:36:22.000000000 -0500
+++ guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h       2008-09-16 
21:40:30.000000000 -0500
@@ -34,6 +34,7 @@ typedef struct g_db_handle
   SCM closed;  /* boolean, TRUE if closed otherwise FALSE */
   void* handle;
   void* db_info;
+  int in_free;
 } gdbi_db_handle_t;
 /* end guile smob struct */
 
Index: guile-dbi-2.0.0/src/guile-dbi.c
===================================================================
--- guile-dbi-2.0.0.orig/src/guile-dbi.c        2008-09-16 21:40:24.000000000 
-0500
+++ guile-dbi-2.0.0/src/guile-dbi.c     2008-09-16 21:40:30.000000000 -0500
@@ -53,6 +53,8 @@ SCM_DEFINE (make_g_db_handle, "dbi-open"
   g_db_handle->bcknd   = bcknd;
   g_db_handle->constr  = conn_string;
   g_db_handle->handle  = NULL;
+  g_db_handle->closed  = SCM_BOOL_T;
+  g_db_handle->in_free = 0;
   g_db_handle->db_info = NULL;
 
   bcknd_str = scm_to_locale_string (bcknd);
@@ -189,6 +191,9 @@ free_db_handle (SCM g_db_handle_smob)
   struct g_db_handle *g_db_handle = NULL;
 
   g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(g_db_handle_smob);
+  if (g_db_handle->in_free) return 0;
+  g_db_handle->in_free = 1;
+
   close_g_db_handle(g_db_handle_smob);
 
   if (g_db_handle != NULL)
@@ -325,7 +330,8 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c
                  20))) == NULL)
     {
       free(bcknd);
-      dbh->status = (SCM) scm_cons(scm_from_int(errno),
+      if (dbh->in_free) return; /* do not SCM anything while in GC */
+      dbh->status = scm_cons(scm_from_int(errno),
                                   scm_makfrom0str(strerror(errno)));
       return;
     }
@@ -335,6 +341,8 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c
   if((ret = dlerror()) != NULL)
     {
       free(bcknd);
+      free(func);
+      if (dbh->in_free) return; /* do not SCM anything while in GC */
       dbh->status = (SCM) scm_cons(scm_from_int(1),
                                   scm_makfrom0str(ret));
       return;
@@ -345,8 +353,10 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c
     {
       free(bcknd);
     }
+
+  if (dbh->in_free) return; /* do not SCM anything while in GC */
   /* todo: error msg to be translated */
-  dbh->status = (SCM) scm_cons(scm_from_int(0),
+  dbh->status = scm_cons(scm_from_int(0),
                           scm_makfrom0str("symbol loaded"));
   return;
 }

Attachment: signature.asc
Description: Digital signature

Reply via email to