ZCGCoder
ZCGCoder

Reputation: 514

Python app crashed with "PyEval_RestoreThread: the function must be called with the GIL held, but the GIL is released"

I have a Python Program, and because it's too big, here's the link to its source code: Link

When I run it on Mac, sometimes I get this weird exception:

Fatal Python error: PyEval_RestoreThread: the function must be called with the GIL held, but the GIL is released (the current Python thread state is NULL)
Python runtime state: initialized

Current thread 0x0000000115f8ce00 (most recent call first):
  File "/usr/local/Cellar/[email protected]/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/tkinter/__init__.py", line 1429 in mainloop
  File ".../PyPlusSource/pyplus.py", line 1435 in <module>

So why is this happenning? Please explain in simple words. Thanks for any ideas!

EDIT:
I'm on MacOS 11.2.3 Big Sur [Not beta], with Python 3.9.2 [Not beta again] installed. And this error is hard to reproduce

Upvotes: 4

Views: 12699

Answers (2)

GaryMBloom
GaryMBloom

Reputation: 5692

I had this happen on my cross-platform app when running on MacOS. The app runs fine on Windows. I tracked down the problem to a line where I was setting a tkinter.StringVar to a value directly. That assignment was triggering a callback function which also changed other tkinter variables. On a hunch, I changed the line from an immediate value change to a delayed/"after_idle" value change. In other words, I changed:

root.my_string_var.set(value)

to:

root.after_idle(root.my_string_var.set, value)

I had learned a bit about thread context from working with Kivy, so I gave the above a try and was successful. I suspect it's a timing/context issue. The crash seemed to be a result of opening a dialog box, which was causing the main app to lose focus. (thus the "GIL" message.). I tried adding a root.force_focus() call, but that didn't help.

Upvotes: 1

In general, this should only possibly happen in a code combining Python with components in other languages (typically C; see, e.g., When the GIL is released?).

From your description, it's not clear which part of your code causes the error (the original question asked 11 days ago says it's line 1435, your video added 6 days ago shows it's line 1452, and the PyPlus code at GitHub you refer to was changed 2 days ago and currently only has 1441 lines) and therefore, you'll need to check yourself where exactly in your code the error is produced.

The error further refers to line 1429 in tkinter/__init__.py which (as far as I can see in my Python 3.9 version of tkinter) is if string: in the following function:

def _getints(self, string):
    """Internal function."""
    if string:
        return tuple(map(self.tk.getint, self.tk.splitlist(string)))

So, it seems that the function is called with undefined variable string.

I have got this PyEval_RestoreThread error a couple of times with various reasons:

  • When a function from a cythonized Python module (.so on Mac) calls a function from another module that was imported only indirectly. For example, if module a.py imports b.py, b.py imports c.py, and a function in a.py uses a function from c.py. When running from PyCharm or from terminal via python3 myprogram.py, there are no errors but as soon as the modules are cythonized, the functions in a.so cannot found the functions from c.so anymore and I get this error.

  • On an uncaught exception in a secondary thread; for example when I haven't checked the type of a variable read from a file and was trying to update a string in my (PySimpleGUI = tkinter-based) GUI with its value that was no string.

Upvotes: 4

Related Questions