# HG changeset patch -- Bitbucket.org
# Project gevent
# URL http://bitbucket.org/denis/gevent/overview
# User Denis Bilenko <denis.bilenko@gmail.com>
# Date 1275064878 -25200
# Node ID aca8c6c649a6e5f15b01f0aa977a654956f78110
# Parent  bbe9526c07991b2c598eb3ce84985502e682fa96
Hub: store/clear/restore current exc_info before/after switching

Index: python-gevent/gevent/hub.py
===================================================================
--- python-gevent.orig/gevent/hub.py	2010-06-16 08:57:42.000000000 +0200
+++ python-gevent/gevent/hub.py	2010-06-16 08:58:34.000000000 +0200
@@ -142,13 +142,18 @@
     def switch(self):
         cur = getcurrent()
         assert cur is not self, 'Cannot switch to MAINLOOP from MAINLOOP'
-        switch_out = getattr(cur, 'switch_out', None)
-        if switch_out is not None:
-            try:
-                switch_out()
-            except:
-                traceback.print_exc()
-        return greenlet.switch(self)
+        exc_info = sys.exc_info()
+        try:
+            sys.exc_clear()
+            switch_out = getattr(cur, 'switch_out', None)
+            if switch_out is not None:
+                try:
+                    switch_out()
+                except:
+                    traceback.print_exc()
+            return greenlet.switch(self)
+        finally:
+            core.set_exc_info(*exc_info)
 
     def run(self):
         global _threadlocal
Index: python-gevent/gevent/core.pyx
===================================================================
--- python-gevent.orig/gevent/core.pyx	2010-06-16 08:58:37.000000000 +0200
+++ python-gevent/gevent/core.pyx	2010-06-16 08:58:50.000000000 +0200
@@ -440,3 +440,26 @@
 
 include "evbuffer.pxi"
 include "evhttp.pxi"
+
+cdef extern from "frameobject.h":
+    ctypedef struct PyThreadState:
+        void* exc_type
+        void* exc_value
+        void* exc_traceback
+
+    PyThreadState* PyThreadState_GET()
+
+def set_exc_info(object typ, object value, object tb):
+    cdef PyThreadState* tstate = PyThreadState_GET()
+    if tstate.exc_type != NULL:
+        Py_DECREF(<object>tstate.exc_type)
+    if tstate.exc_value != NULL:
+        Py_DECREF(<object>tstate.exc_value)
+    if tstate.exc_traceback != NULL:
+        Py_DECREF(<object>tstate.exc_traceback)
+    Py_INCREF(typ)
+    Py_INCREF(value)
+    Py_INCREF(tb)
+    tstate.exc_type = <void*>typ
+    tstate.exc_value = <void *>value
+    tstate.exc_traceback = <void *>tb
