Author: ArcRiley
Date: 2009-01-09 23:02:10 -0500 (Fri, 09 Jan 2009)
New Revision: 1456

Modified:
   trunk/concordance/examples/echo.py
   trunk/concordance/src/Core.c
Log:
now typechecks callback returns to do the right thing (ie, not segfault)


Modified: trunk/concordance/examples/echo.py
===================================================================
--- trunk/concordance/examples/echo.py  2009-01-09 23:04:06 UTC (rev 1455)
+++ trunk/concordance/examples/echo.py  2009-01-10 04:02:10 UTC (rev 1456)
@@ -29,7 +29,7 @@
 class newcore(concordance.Core) :
   def clientHandle(self, input) :
     print(":%s" % input)
-    return ""
+    return
 
 nc = newcore()
 nc()

Modified: trunk/concordance/src/Core.c
===================================================================
--- trunk/concordance/src/Core.c        2009-01-09 23:04:06 UTC (rev 1455)
+++ trunk/concordance/src/Core.c        2009-01-10 04:02:10 UTC (rev 1456)
@@ -21,6 +21,7 @@
 
 #include "Core.h"
 
+static void       conCore_queueFreeMsg  (conCoreQueueMsg*);
 static gpointer   conCore_loop          (gpointer);
 static int        conCore_listenChannel (conCoreObject*, conChannel*);
 static gboolean   conCore_listenNew     (GIOChannel*, GIOCondition, gpointer);
@@ -298,8 +299,9 @@
       popped = g_async_queue_timed_pop(self->queueRecv, &popEnd);
       Py_END_ALLOW_THREADS
 
-      /* return to start of loop if NULL is returned */
-      if (!popped) continue;
+      /* return to start of loop if the pop call timed out */
+      if (!popped)
+        continue;
 
       /* build argument tuple
 
@@ -322,25 +324,70 @@
       handle = PyObject_GetAttrString(s, "clientHandle");
       output = PyEval_CallObject(handle, tinput);
 
-      /* reset popped->message to reuse with response, convert utf16 to utf8
+      /* free the objects we're done with
 
-         GString*       g_string_assign          (GString *string,
+         void           Py_DECREF                (PyObject *o);
+      */
+      Py_DECREF(handle);
+      Py_DECREF(tinput);
+      Py_DECREF(sinput);
+
+      if (!output) {
+        /* free message struct and exit here if callback raised an error */
+        conCore_queueFreeMsg(popped);
+        break;
+      }
+
+      /* if output is None, decref it, free message struct, and continue */
+      if (output == Py_None) {
+        Py_DECREF(output);
+        conCore_queueFreeMsg(popped);
+        continue;
+      }
+
+      /* ensure output is PyUnicode_Type (since it's not None)
+
+         int            PyUnicode_Check          (PyObject *o);
+      */
+      if (!PyUnicode_Check(output)) {
+        /* free whatever was returned and raise an error
+
+           void         Py_DECREF                (PyObject *o);
+           void         PyErr_SetString          (PyObject *type,
+                                                  const char *message);
+        */
+        Py_DECREF(output);
+        conCore_queueFreeMsg(popped);
+        PyErr_SetString(PyExc_TypeError,
+                        "handle must return a Unicode string or None");
+        return NULL;
+      }
+
+      /* only use output when non-empty
+
+         Py_ssize_t     PyUnicode_GetSize        (PyObject *unicode);
+      */
+      if (PyUnicode_GetSize(output)) {
+        /* convert unicode to utf8, reusing popped->message for response
+
+           GString*     g_string_assign          (GString *string,
                                                   const gchar *rval);
-         void           g_async_queue_push       (GAsyncQueue *queue,
+           void         g_async_queue_push       (GAsyncQueue *queue,
                                                   gpointer data);
-      */
-      popped->message = g_string_assign(popped->message,
-                                        conPyUnicodeToUTF8(output));
-      g_async_queue_push(self->queueSend, popped);
+        */
+        popped->message = g_string_assign(popped->message,
+                                          conPyUnicodeToUTF8(output));
+        g_async_queue_push(self->queueSend, popped);
+      }
+      else
+        /* free message struct since we didn't use it */
+        conCore_queueFreeMsg(popped);
 
-      /* free the objects we're done with
+      /* free the output object
 
          void           Py_DECREF                (PyObject *o);
       */
       Py_DECREF(output);
-      Py_DECREF(handle);
-      Py_DECREF(tinput);
-      Py_DECREF(sinput);
     }
 
     /* signal was raised, return with error condition */
@@ -351,6 +398,26 @@
   #
   ###########################################################################
   #
+  # Convenience functions
+  #                                                                        */
+
+  static void
+  conCore_queueFreeMsg(conCoreQueueMsg* msg) {
+    /* free message struct and it's members
+
+       gchar*           g_string_free            (GString *string,
+                                                  gboolean free_segment);
+       void             g_free                   (gpointer mem);
+    */
+    g_string_free(msg->message, TRUE);
+    g_free(msg);
+  }
+
+
+  /*
+  #
+  ###########################################################################
+  #
   # MainLoop thread functions (nogil)
   #                                                                        */
 
@@ -611,15 +678,8 @@
     pop = g_async_queue_pop(self->queueSend);
     conCore_sessionSend(pop->session, pop->message->str, pop->message->len);
 
-    /* free popped message before returning
-
-       gchar*           g_string_free            (GString *string,
-                                                  gboolean free_segment);
-       void             g_free                   (gpointer mem);
-    */
-    g_string_free(pop->message, TRUE);
-    g_free(pop);
-
+    /* free popped message struct and return */
+    conCore_queueFreeMsg(pop);
     return TRUE;
   }
 

_______________________________________________
PySoy-SVN mailing list
PySoy-SVN@pysoy.org
http://www.pysoy.org/mailman/listinfo/pysoy-svn

Reply via email to