@@ -1799,8 +1799,15 @@ static PyObject *
1799
1799
gen_reduce (PyGenObject * gen )
1800
1800
{
1801
1801
PyObject * tup ;
1802
- PyObject * frame_reducer ;
1803
- frame_reducer = slp_reduce_frame (gen -> gi_frame );
1802
+ PyObject * frame_reducer = (PyObject * )gen -> gi_frame ;
1803
+ if (frame_reducer == NULL ) {
1804
+ /* Pickle NULL as None. See gen_setstate() for the corresponding
1805
+ * unpickling code. */
1806
+ Py_INCREF (Py_None );
1807
+ frame_reducer = Py_None ;
1808
+ } else {
1809
+ frame_reducer = slp_reduce_frame (gen -> gi_frame );
1810
+ }
1804
1811
if (frame_reducer == NULL )
1805
1812
return NULL ;
1806
1813
tup = Py_BuildValue ("(O()(Oi))" ,
@@ -1833,24 +1840,53 @@ gen_setstate(PyObject *self, PyObject *args)
1833
1840
{
1834
1841
PyGenObject * gen = (PyGenObject * ) self ;
1835
1842
PyFrameObject * f ;
1843
+ PyObject * obj ;
1836
1844
int gi_running ;
1837
1845
1838
1846
if (is_wrong_type (Py_TYPE (self ))) return NULL ;
1839
1847
1840
1848
if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
1841
1849
return NULL ;
1842
1850
1843
- if (!PyArg_ParseTuple (args , "O!i :generator" ,
1844
- & PyFrame_Type , & f , & gi_running )) {
1851
+ if (!PyArg_ParseTuple (args , "Oi :generator" ,
1852
+ & obj , & gi_running )) {
1845
1853
Py_DECREF (args );
1846
1854
return NULL ;
1847
1855
}
1848
- Py_DECREF (args );
1856
+
1857
+ if (obj == Py_None ) {
1858
+ /* No frame, generator is exhausted */
1859
+ Py_CLEAR (gen -> gi_frame );
1860
+
1861
+ /* Even if gi_frame is NULL, gi_code is still valid. Therefore
1862
+ * I set it to the code of the exhausted frame singleton.
1863
+ */
1864
+ assert (gen_exhausted_frame != NULL );
1865
+ assert (PyFrame_Check (gen_exhausted_frame ));
1866
+ obj = (PyObject * )gen_exhausted_frame -> f_code ;
1867
+ Py_INCREF (obj );
1868
+ Py_SETREF (gen -> gi_code , obj );
1869
+
1870
+ gen -> gi_running = gi_running ;
1871
+ Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1872
+ Py_INCREF (gen );
1873
+ Py_DECREF (args ); /* holds the obj ref */
1874
+ return (PyObject * )gen ;
1875
+ }
1876
+ if (!PyFrame_Check (obj )) {
1877
+ PyErr_SetString (PyExc_TypeError ,
1878
+ "invalid frame object for gen_setstate" );
1879
+ Py_DECREF (args ); /* holds the obj ref */
1880
+ return NULL ;
1881
+ }
1882
+ f = (PyFrameObject * )obj ;
1883
+ obj = NULL ;
1849
1884
1850
1885
if (!gi_running ) {
1851
1886
if ((f = slp_ensure_new_frame (f )) != NULL ) {
1852
1887
/* use a second one for late initialization */
1853
1888
PyGenObject * tmpgen ;
1889
+ Py_DECREF (args ); /* holds the frame ref */
1854
1890
/* PyGenerator_New eats an existing reference */
1855
1891
if ((tmpgen = (PyGenObject * )
1856
1892
PyGen_New (f )) == NULL ) {
@@ -1884,6 +1920,7 @@ gen_setstate(PyObject *self, PyObject *args)
1884
1920
* generator without the corresponding tasklet.
1885
1921
*/
1886
1922
Py_INCREF (f );
1923
+ Py_DECREF (args ); /* holds the frame ref */
1887
1924
Py_SETREF (gen -> gi_frame , f );
1888
1925
Py_INCREF (f -> f_code );
1889
1926
Py_SETREF (gen -> gi_code , (PyObject * )f -> f_code );
0 commit comments