@@ -2232,29 +2232,12 @@ static int init_methodwrappertype(void)
2232
2232
2233
2233
******************************************************/
2234
2234
2235
- /* Note: this definition is not compatible to 2.2.3, since
2236
- the gi_weakreflist does not exist. Therefore, we don't
2237
- create the object ourselves, but use the provided function
2238
- with a fake frame. The gi_weakreflist is not touched.
2239
- */
2240
-
2241
- typedef struct {
2242
- PyObject_HEAD
2243
- /* The gi_ prefix is intended to remind of generator-iterator. */
2244
-
2245
- PyFrameObject * gi_frame ;
2246
-
2247
- /* True if generator is being executed. */
2248
- char gi_running ;
2249
-
2250
- /* List of weak reference. */
2251
- PyObject * gi_weakreflist ;
2252
- } genobject ;
2253
-
2254
2235
static PyTypeObject wrap_PyGen_Type ;
2236
+ /* Used to initialize a generator created by gen_new. */
2237
+ static PyFrameObject * gen_exhausted_frame ;
2255
2238
2256
2239
static PyObject *
2257
- gen_reduce (genobject * gen )
2240
+ gen_reduce (PyGenObject * gen )
2258
2241
{
2259
2242
PyObject * tup ;
2260
2243
tup = Py_BuildValue ("(O()(Oi))" ,
@@ -2268,11 +2251,13 @@ gen_reduce(genobject *gen)
2268
2251
static PyObject *
2269
2252
gen_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
2270
2253
{
2271
- genobject * gen ;
2272
-
2254
+ PyGenObject * gen ;
2273
2255
if (is_wrong_type (type )) return NULL ;
2274
- Py_INCREF (Py_None );
2275
- gen = (genobject * ) PyGenerator_New ((PyFrameObject * ) Py_None );
2256
+
2257
+ /* A reference to frame is stolen by PyGen_New. */
2258
+ assert (gen_exhausted_frame != NULL );
2259
+ assert (PyFrame_Check (gen_exhausted_frame ));
2260
+ gen = (PyGenObject * ) PyGen_New (slp_ensure_new_frame (gen_exhausted_frame ));
2276
2261
if (gen == NULL )
2277
2262
return NULL ;
2278
2263
Py_TYPE (gen ) = type ;
@@ -2282,7 +2267,7 @@ gen_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2282
2267
static PyObject *
2283
2268
gen_setstate (PyObject * self , PyObject * args )
2284
2269
{
2285
- genobject * gen = (genobject * ) self ;
2270
+ PyGenObject * gen = (PyGenObject * ) self ;
2286
2271
PyFrameObject * f ;
2287
2272
int gi_running ;
2288
2273
@@ -2294,16 +2279,17 @@ gen_setstate(PyObject *self, PyObject *args)
2294
2279
if (!gi_running ) {
2295
2280
if ((f = slp_ensure_new_frame (f )) != NULL ) {
2296
2281
/* use a second one for late initialization */
2297
- genobject * tmpgen ;
2282
+ PyGenObject * tmpgen ;
2298
2283
/* PyGenerator_New eats an existing reference */
2299
- if ((tmpgen = (genobject * )
2300
- PyGenerator_New (f )) == NULL ) {
2284
+ if ((tmpgen = (PyGenObject * )
2285
+ PyGen_New (f )) == NULL ) {
2301
2286
Py_DECREF (f );
2302
2287
return NULL ;
2303
2288
}
2304
2289
Py_INCREF (f );
2305
- Py_CLEAR (gen -> gi_frame );
2306
- gen -> gi_frame = f ;
2290
+ Py_SETREF (gen -> gi_frame , f );
2291
+ Py_INCREF (f -> f_code );
2292
+ Py_SETREF (gen -> gi_code , (PyObject * )f -> f_code );
2307
2293
/* The frame the temporary generator references
2308
2294
will have GeneratorExit raised on it, when the
2309
2295
temporary generator is torn down. So clearing
@@ -2327,8 +2313,9 @@ gen_setstate(PyObject *self, PyObject *args)
2327
2313
* generator without the corresponding tasklet.
2328
2314
*/
2329
2315
Py_INCREF (f );
2330
- Py_CLEAR (gen -> gi_frame );
2331
- gen -> gi_frame = f ;
2316
+ Py_SETREF (gen -> gi_frame , f );
2317
+ Py_INCREF (f -> f_code );
2318
+ Py_SETREF (gen -> gi_code , (PyObject * )f -> f_code );
2332
2319
gen -> gi_running = gi_running ;
2333
2320
Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
2334
2321
Py_INCREF (gen );
@@ -2343,10 +2330,10 @@ DEF_INVALID_EXEC(gen_iternext_callback)
2343
2330
static int init_generatortype (void )
2344
2331
{
2345
2332
int res ;
2346
- genobject * gen = (genobject * ) run_script (
2347
- "def f (): yield 42\n" /* define a generator */
2348
- "g = f ()\n" /* instanciate it */
2349
- "g.__next__()\n" , "g" ); /* force callback frame creation */
2333
+ PyGenObject * gen = (PyGenObject * ) run_script (
2334
+ "def exhausted_generator (): yield 42\n" /* define a generator */
2335
+ "g = exhausted_generator ()\n" /* instanciate it */
2336
+ "g.__next__()\n" , "g" ); /* force callback frame creation */
2350
2337
PyFrameObject * cbframe ;
2351
2338
2352
2339
if (gen == NULL || gen -> gi_frame -> f_back == NULL )
@@ -2356,6 +2343,13 @@ static int init_generatortype(void)
2356
2343
gen -> gi_frame -> f_back -> f_execute ,
2357
2344
REF_INVALID_EXEC (gen_iternext_callback ))
2358
2345
|| init_type (& wrap_PyGen_Type , initchain );
2346
+
2347
+ assert (gen_exhausted_frame == NULL );
2348
+ gen_exhausted_frame = slp_ensure_new_frame (gen -> gi_frame );
2349
+ if (gen_exhausted_frame == NULL ) {
2350
+ return -1 ;
2351
+ }
2352
+
2359
2353
Py_DECREF (gen );
2360
2354
return res ;
2361
2355
}
@@ -2458,23 +2452,36 @@ slp_pickle_moduledict(PyObject *self, PyObject *args)
2458
2452
source module initialization
2459
2453
2460
2454
******************************************************/
2455
+ static int
2456
+ _wrapmodule_traverse (PyObject * self , visitproc visit , void * arg )
2457
+ {
2458
+ Py_VISIT (gen_exhausted_frame );
2459
+ return 0 ;
2460
+ }
2461
+
2462
+ static int
2463
+ _wrapmodule_clear (PyObject * self )
2464
+ {
2465
+ Py_CLEAR (gen_exhausted_frame );
2466
+ return 0 ;
2467
+ }
2468
+
2461
2469
static struct PyModuleDef _wrapmodule = {
2462
2470
PyModuleDef_HEAD_INIT ,
2463
2471
"_stackless._wrap" ,
2464
2472
NULL ,
2465
2473
-1 ,
2466
2474
NULL ,
2467
2475
NULL ,
2468
- NULL ,
2469
- NULL ,
2476
+ _wrapmodule_traverse ,
2477
+ _wrapmodule_clear ,
2470
2478
NULL
2471
2479
};
2472
2480
2473
2481
PyObject *
2474
2482
init_prickelpit (void )
2475
2483
{
2476
2484
PyObject * copy_reg , * tmp ;
2477
- int ret = 0 ;
2478
2485
2479
2486
types_mod = PyModule_Create (& _wrapmodule );
2480
2487
if (types_mod == NULL )
@@ -2491,7 +2498,11 @@ init_prickelpit(void)
2491
2498
Py_CLEAR (types_mod );
2492
2499
return NULL ;
2493
2500
}
2494
- ret = initchain ();
2501
+ if (initchain ()) {
2502
+ Py_CLEAR (pickle_reg );
2503
+ Py_CLEAR (types_mod );
2504
+ return NULL ;
2505
+ }
2495
2506
Py_CLEAR (pickle_reg );
2496
2507
tmp = types_mod ;
2497
2508
types_mod = NULL ;
0 commit comments