@@ -1706,8 +1706,15 @@ static PyObject *
17061706gen_reduce (PyGenObject * gen )
17071707{
17081708 PyObject * tup ;
1709- PyObject * frame_reducer ;
1710- frame_reducer = slp_reduce_frame (gen -> gi_frame );
1709+ PyObject * frame_reducer = (PyObject * )gen -> gi_frame ;
1710+ if (frame_reducer == NULL ) {
1711+ /* Pickle NULL as None. See gen_setstate() for the corresponding
1712+ * unpickling code. */
1713+ Py_INCREF (Py_None );
1714+ frame_reducer = Py_None ;
1715+ } else {
1716+ frame_reducer = slp_reduce_frame (gen -> gi_frame );
1717+ }
17111718 if (frame_reducer == NULL )
17121719 return NULL ;
17131720 tup = Py_BuildValue ("(O()(OiOO))" ,
@@ -1742,6 +1749,7 @@ gen_setstate(PyObject *self, PyObject *args)
17421749{
17431750 PyGenObject * gen = (PyGenObject * ) self ;
17441751 PyFrameObject * f ;
1752+ PyObject * obj ;
17451753 int gi_running ;
17461754 PyObject * name = NULL ;
17471755 PyObject * qualname = NULL ;
@@ -1751,12 +1759,50 @@ gen_setstate(PyObject *self, PyObject *args)
17511759 if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
17521760 return NULL ;
17531761
1754- if (!PyArg_ParseTuple (args , "O!i |OO:generator" ,
1755- & PyFrame_Type , & f , & gi_running , & name , & qualname )) {
1762+ if (!PyArg_ParseTuple (args , "Oi |OO:generator" ,
1763+ & obj , & gi_running , & name , & qualname )) {
17561764 Py_DECREF (args );
17571765 return NULL ;
17581766 }
1759- Py_DECREF (args );
1767+
1768+ if (obj == Py_None ) {
1769+ /* No frame, generator is exhausted */
1770+ Py_CLEAR (gen -> gi_frame );
1771+
1772+ /* Even if gi_frame is NULL, gi_code is still valid. Therefore
1773+ * I set it to the code of the exhausted frame singleton.
1774+ */
1775+ assert (gen_exhausted_frame != NULL );
1776+ assert (PyFrame_Check (gen_exhausted_frame ));
1777+ obj = (PyObject * )gen_exhausted_frame -> f_code ;
1778+ Py_INCREF (obj );
1779+ Py_SETREF (gen -> gi_code , obj );
1780+
1781+ gen -> gi_running = gi_running ;
1782+ if (name == NULL ) {
1783+ name = gen_exhausted_frame -> f_code -> co_name ;
1784+ assert (name != NULL );
1785+ }
1786+ if (qualname == NULL ) {
1787+ qualname = name ;
1788+ }
1789+ Py_INCREF (name );
1790+ Py_SETREF (gen -> gi_name , name );
1791+ Py_INCREF (qualname );
1792+ Py_SETREF (gen -> gi_qualname , qualname );
1793+ Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1794+ Py_INCREF (gen );
1795+ Py_DECREF (args ); /* holds the obj ref */
1796+ return (PyObject * )gen ;
1797+ }
1798+ if (!PyFrame_Check (obj )) {
1799+ PyErr_SetString (PyExc_TypeError ,
1800+ "invalid frame object for gen_setstate" );
1801+ Py_DECREF (args ); /* holds the obj ref */
1802+ return NULL ;
1803+ }
1804+ f = (PyFrameObject * )obj ;
1805+ obj = NULL ;
17601806
17611807 if (name == NULL ) {
17621808 name = f -> f_code -> co_name ;
@@ -1774,6 +1820,7 @@ gen_setstate(PyObject *self, PyObject *args)
17741820 if ((tmpgen = (PyGenObject * )
17751821 PyGen_NewWithQualName (f , NULL , NULL )) == NULL ) {
17761822 Py_DECREF (f );
1823+ Py_DECREF (args ); /* holds the frame and name refs */
17771824 return NULL ;
17781825 }
17791826 Py_INCREF (f );
@@ -1796,6 +1843,7 @@ gen_setstate(PyObject *self, PyObject *args)
17961843 }
17971844 else
17981845 gen = NULL ;
1846+ Py_DECREF (args ); /* holds the frame and name refs */
17991847 return (PyObject * ) gen ;
18001848 }
18011849
@@ -1817,6 +1865,7 @@ gen_setstate(PyObject *self, PyObject *args)
18171865 Py_SETREF (gen -> gi_qualname , qualname );
18181866 Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
18191867 Py_INCREF (gen );
1868+ Py_DECREF (args ); /* holds the frame and name refs */
18201869 return (PyObject * )gen ;
18211870}
18221871
0 commit comments