I'm trying to create a program to run on an embedded raspberry pi to perform many LabView-esque functionalities for a lab testing device. To do this, I'm using Tkinter for the GUI at the request of the person paying for it. Ideally, I'd like to get it so that the Tkinter GUI is still functional while a test is running, so that the user can change test params on the fly (its a mechanical cycle testing application). To accomplish this without having the GUI loop lock-up, I've created a parallel process to handle the data collection, where I have contained all of the calls to the U3 module. This alone works fine, and the Tkinter app alone also works great.
The problem is that when Tkinter and u3.U3 are initialized in different processes, I get the following error message:
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
I'm running the code currently on OSX 10.11 (El Cap) and the Pi has raspbian linux (the pi doesn't have the horsepower to use good IDEs which is why I develop on OSX)
I realize this problem would probably be fixed by using threading instead of multiprocessing, however Tkinter has a history of misbehaving under these conditions, and whenever it isn't in the __main__ thread.
Any known solutions? All help appreciated.
I've isolated the problem to the attached Python 2.7 script.
Looking through the problem report, it looks like the error occurs in the third party USB library we use, libusb-1.0, and some of its Apple Core Foundation usage. There seems to be a conflict under certain conditions when using Tkinter, multiprocessing and Exodriver (using libusb-1.0) together on a Mac. This doesn't look like an issue we can resolve in our Exodriver or LabJackPython code.
One workaround, at least with your code, is to start the multi processes up first, and then "import Tkinter". For my test I moved the Tkinter import and Idle class to a idle.py file and changed your main code to the following:
if __name__ == "__main__":
# create the backend data process
BTABackends = mp.Process(target=GrabSomeData)
BTABackends.daemon = True
BTABackends.name = 'TesterBackend'
BTABackends.start()
from idle import Idle
sit_here = Idle()
sit_here.mainloop()
Alternatively, you can develop on a Linux machine where the error doesn't occur. I didn't test on a Raspberry Pi, but our machine running Fedora ran your code without issue.
Thanks for the quick feedback, the code worked seamlessly on Linux, both Ubuntu and Raspbian didn't have trouble.