@@ -111,20 +111,27 @@ static PyObject* walk_function(PyObject* op, stack* frontier)
111111
112112 _Py_SetImmutable (op );
113113
114-
115114 f = (PyFunctionObject * )op ;
116115
116+
117117 globals = f -> func_globals ;
118118 builtins = f -> func_builtins ;
119119
120- if (PyUnicode_CompareWithASCIIString (f -> func_module , "_frozen_importlib" ) == 0 ){
121- // we don't want to freeze the importlib module
122- Py_RETURN_NONE ;
123- }
124-
125120 module = PyImport_Import (f -> func_module );
126121 if (module == NULL ){
127- return module ;
122+ // clear the exception so we can check if the module is a namedtuple
123+ PyObject * exc = PyErr_GetRaisedException ();
124+ _Py_DECLARE_STR (namedtuple , "namedtuple" );
125+ _Py_DECLARE_STR (startswith , "startswith" );
126+ PyObject * res = PyObject_CallMethodOneArg (f -> func_module , & _Py_STR (startswith ), & _Py_STR (namedtuple ));
127+ if (Py_IsTrue (res )){
128+ // namedtuple creates a fake module, which cannot be imported
129+ Py_RETURN_NONE ;
130+ }
131+
132+ // not a namedtuple, so we need to set the exception
133+ PyErr_SetRaisedException (exc );
134+ return NULL ;
128135 }
129136
130137 if (PyModule_Check (module )){
@@ -294,18 +301,6 @@ static PyObject* walk_function(PyObject* op, stack* frontier)
294301
295302static int _freeze_visit (PyObject * obj , void * frontier )
296303{
297- if (PyModule_Check (obj )){
298- const char * name = PyModule_GetName (obj );
299-
300- if (strcmp (name , "_frozen_importlib_external" ) == 0 ){
301- return 0 ;
302- }
303-
304- if (strcmp (name , "_frozen_importlib" ) == 0 ){
305- return 0 ;
306- }
307- }
308-
309304 if (!_Py_IsImmutable (obj )){
310305 if (stack_push ((stack * )frontier , obj )){
311306 PyErr_NoMemory ();
@@ -332,9 +327,39 @@ PyObject* _Py_Freeze(PyObject* obj)
332327 return PyErr_NoMemory ();
333328 }
334329
330+ PyObject * frozen_importlib = PyImport_ImportModule ("_frozen_importlib" );
331+ if (frozen_importlib == NULL ){
332+ stack_free (frontier );
333+ return NULL ;
334+ }
335+
336+ PyObject * blocking_on = PyObject_GetAttrString (frozen_importlib , "_blocking_on" );
337+ if (blocking_on == NULL ){
338+ Py_DECREF (frozen_importlib );
339+ stack_free (frontier );
340+ return NULL ;
341+ }
342+
343+ PyObject * module_locks = PyObject_GetAttrString (frozen_importlib , "_module_locks" );
344+ if (module_locks == NULL ){
345+ Py_DECREF (blocking_on );
346+ Py_DECREF (frozen_importlib );
347+ stack_free (frontier );
348+ return NULL ;
349+ }
350+
351+ Py_DECREF (frozen_importlib );
352+
335353 while (!stack_empty (frontier )){
336354 PyObject * item = stack_pop (frontier ); // item.rc = x + 1
337355
356+ if (item == blocking_on ||
357+ item == module_locks ){
358+ // the module lock and blocking on dictionaries must remain mutable or else
359+ // we will not be able to import modules
360+ continue ;
361+ }
362+
338363 PyTypeObject * type = Py_TYPE (item );
339364 traverseproc traverse ;
340365 PyObject * type_op = NULL ;
@@ -354,6 +379,8 @@ PyObject* _Py_Freeze(PyObject* obj)
354379 if (PyFunction_Check (item )){
355380 PyObject * err = walk_function (item , frontier );
356381 if (!Py_IsNone (err )){
382+ Py_DECREF (blocking_on );
383+ Py_DECREF (module_locks );
357384 stack_free (frontier );
358385 return err ;
359386 }
@@ -363,6 +390,8 @@ PyObject* _Py_Freeze(PyObject* obj)
363390 traverse = type -> tp_traverse ;
364391 if (traverse != NULL ){
365392 if (traverse (item , (visitproc )_freeze_visit , frontier )){
393+ Py_DECREF (blocking_on );
394+ Py_DECREF (module_locks );
366395 stack_free (frontier );
367396 return NULL ;
368397 }
@@ -373,12 +402,16 @@ PyObject* _Py_Freeze(PyObject* obj)
373402 if (!_Py_IsImmutable (type_op )){
374403 if (stack_push (frontier , type_op ))
375404 {
405+ Py_DECREF (blocking_on );
406+ Py_DECREF (module_locks );
376407 stack_free (frontier );
377408 return PyErr_NoMemory ();
378409 }
379410 }
380411 }
381412
413+ Py_DECREF (blocking_on );
414+ Py_DECREF (module_locks );
382415 stack_free (frontier );
383416
384417 Py_RETURN_NONE ;
@@ -390,22 +423,12 @@ PyObject* _Py_FreezeGlobals()
390423 PyObject * main_dict ;
391424 PyInterpreterState * main ;
392425
393- // we will need to exclude importlib from this process
394- PyObject * importlib = PyUnicode_FromString ("importlib" );
395- if (importlib == NULL ){
396- return NULL ;
397- }
398-
399426 // go module by module and freeze their global dictionaries
400427 PyObject * modules = PyImport_GetModuleDict ();
401428 Py_ssize_t size = PyDict_Size (modules );
402429 PyObject * keys = PyDict_Keys (modules );
403430 for (Py_ssize_t i = 0 ; i < size ; i ++ ){
404431 PyObject * key = PyList_GetItem (keys , i );
405- if (PyUnicode_Contains (key , importlib )){
406- continue ;
407- }
408-
409432 PyObject * module = PyDict_GetItem (modules , key );
410433 PyObject * globals = PyModule_GetDict (module );
411434 ret = _Py_Freeze (globals );
@@ -416,7 +439,6 @@ PyObject* _Py_FreezeGlobals()
416439 }
417440
418441 Py_DECREF (keys );
419- Py_DECREF (importlib );
420442
421443 main = PyInterpreterState_Main ();
422444 if (main == NULL ){
0 commit comments