0

I've written a program that uses tkinter to create a GUI, and in the GUI I have a button that starts a program that connects to a socket and reads in messages with signal information. I needed this to happen constantly in the background, because I had other functionality I needed accessible on the GUI, but the GUI would be locked.

So I wrote code that would run that button in a new thread.


# Run everything after connect in a separate thread, so the GUI is not locked
def _start_connect_thread(self, event):
    HOST = self.ip_e.get()
    PORT = int(self.port_e.get())
    global connect_thread
    connect_thread = threading.Thread(target=self.connect, kwargs={'host': HOST, 'port': PORT})
    connect_thread.daemon = True
    connect_thread.start()


# Connect TaskTCS and StreamingDataService to AIMS
def connect(self, host=None, port=None):

    print("Connecting sensor tasking program to AIMS...")
    self.tt = TaskTCS(host, port)
    print("Connecting streaming data program to AIMS...")
    self.sd = StreamingData(host, port)

    # Run Streaming Data Service, which will pull all streaming data from sensor
    self.sd.run()

With this code, my GUI is free to perform other tasks. Most importantly, I can press a button that plots the data coming in from the sensor. When I press the plot button, a flag is toggled in the sd class, and it uses the information coming from the sensor to plot it with matplotlib. Inside the sd class is a function that is running on a while loop, unpacking information from the sensor and checking if the flag is toggled in order to know when to plot it.

Is this not thread safe?

The reason I ask is this program works perfectly fine on the machine I'm working on. However, when I try to run this with anaconda3 python, I get these errors.

libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
QObject::setParent: Cannot set parent, new parent is in a different thread
QObject::setParent: Cannot set parent, new parent is in a different thread

I'm not sure if these errors are from anaconda, or if it's from non-thread-safe coding.

When this program was attempted to run on a machine that had python 2.6, it got this error when clicking the connect button:

Exception in thread Thread-1:
Trackback (most recent call last):
File .usr/lib64/python2.6/threading.py line 532 in _bootstart_inner self.run()
File /usr/lib64/python2.6/threading.py, line 484, in run self._target(*self._args, **self._kwargs)
File “WaterfallGUI.py”, line 282 in connect HOST = self.ip_e.get()
File “/usr/lib64/python2.6/lib-tk/Tkinter.py”, line 2372, in get return self.tk.call(self._w,’get’)
TclError: out of stack space (infinite loop?)

So can a program somehow not have issues with threads on one machine but it can on others?

Note: In an attempt to solve the second error, I moved the .get() functions in the _start_connect_thread function to before actually starting the thread. Before, I was calling those functions in connect. Because I'm calling tkinter getters in a different thread, could that have been the issue in that case? If so, why wouldn't it cause an error on my machine on python 2.7? This was the old code:

 def _start_connect_thread(self, event):
    global connect_thread
    connect_thread = threading.Thread(target=self.connect)
    connect_thread.daemon = True
    connect_thread.start()
    
 def connect(self):
    HOST = self.ip_e.get()
    PORT = int(self.port_e.get())
    
    ...

I don't believe I'm calling anything tkinter GUI related outside of the main loop in the rest of my code. I see stuff about queues but I can't tell if I need to implement that in my code.

  • Most likely the problem is differences between the python environments on the two machines, i.e. not the machines themselves, unless there are obvious differences like they don't have the same OS/x64-ness/... which you don't specify. Can you make the python_packages identical (including x64-ness) between them and check if it all works as expected? – DisappointedByUnaccountableMod Jul 29 '20 at 12:14
  • I doubt they have the same environment, but I can't confirm. If they don't, my threading code won't work for some but will for others? Ideally, my code would be able to work in different environments. I think the solution will be dockerized, so I may just be able to force a specific environment, but I want to be able to use python 3 with anaconda so I can use more libraries, and I can't tell if threading is causing issues on there. Why does a different environment prevent it from working, and how could I fix that? – Brandon Ryan Jul 29 '20 at 12:19
  • Using e.g. PyInstaller means for a particular OS+version you can bundle up all the dependencies with your code so you aren't dependent on having Python installed or any non-built-in packages, i.e. you're not dependent on the versions in that env. – DisappointedByUnaccountableMod Jul 29 '20 at 12:25
  • Gotcha, so if the code is thread safe in at least one environment, it isn't an issue with thread safety? – Brandon Ryan Jul 29 '20 at 12:36

2 Answers2

2

A program can work on one machine and not on another, but "thread safety" these days means that the program provably does not invoke any "undefined behaviors" of the language that it's written in or the libraries that it uses.

If there's some machine where the program does not "work," and some other machine where it does work, then that pretty much proves that the program is not "thread safe."

The reason I ask is...when I try to run this with anaconda3 python, I get these errors...

Oh. Python.

That's not really a well specified language. It's more like a family of similar languages. You're not necessarily just running the program on a different machine, you're also porting it to what may be a subtly different language.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
1

No, this is not possible. Either code is thread-safe or it isn't. Thread-safety is a property of the algorithms/code, not the target machine. As indicated in the comments, this is far more likely due to an environment setup difference than something about the machine.

That being said, I'm not convinced that this is exactly a thread-safety issue at all. I'm admittedly not terribly familiar with this particular GUI framework, so I could be wrong here, but based on references like this, it seems like you're trying to "directly" update the GUI from another thread, which isn't permitted. (This is actually a very common restriction; WPF, for example, has the exact same rule).

  • I don't believe that's what I'm doing, the plot isn't embedded into the GUI, it's opened in a separate window. I could be wrong about some aspect of my code though. But it sounds like if I can run my code through and through in one environment, the code is thread safe? That's the most important part I think I need to be sure of. I just don't understand how I could get that out of stack space error in one environment and not another. – Brandon Ryan Jul 29 '20 at 12:34