Search code examples
pythonmultithreadingraspberry-pikivyraspbian

how to write a multithread kivy game(on rasp Pi) that can listen to a port at the same time


I am writing a remote-control snake game on Raspberry Pi using kivy(output to the 7" display). The socket is supposed to listen to the port while the game is running. However it turns out that game loop and socketIO's wait loop can not run together. I tried multithreading but it didn't work as expected.

Code for socketIO:

from socketIO_client import SocketIO, BaseNamespace
class Namespace(BaseNamespace):
    def on_connect(self):
        print('[Connected]')
    def on_message(self,packet):
        print packet
        self.get_data(packet)        

    def get_data(self, packet):        
        if(type(packet) is str):
            matches = re.findall(PATTERN, packet)            
            if(matches[0][0]=='2'):                
                dataMatches = re.findall(DATAPATTERN, matches[0][4])
                print dataMatches
                ......

Code for main that definitely does not work:

if __name__ == '__main__':
    MyKeyboardListener() #keyboard listener, works fine
    SnakeApp().run()
    socketIO = SocketIO('10.0.0.4',8080,Namespace)
    socketIO.wait()

I tried the following multithreading, but it didn't work:

if __name__ == '__main__':
    MyKeyboardListener() #keyboard listener, works fine
    threading.Thread(target = SnakeApp().run).start() #results in abort
    socketIO = SocketIO('10.0.0.4',8080,Namespace)
    socketIO.wait()

The above code results in making program to abort with error message :"Fatal Python error: (pygame parachute) Segmentation Fault Aborted"

I also tried another multithreading method but it didn't work as well. This is really frustrating. Is there any way to let game loop and socketIO's wait loop run at the same time? or I just missed something?

UPDATE: working code for main:

def connect_socket():
    socketIO = SocketIO('10.0.0.4',8080,Namespace)
    socketIO.wait()
if __name__ == '__main__':
    MyKeyboardListener() #keyboard listener, works fine
    socketThread = threading.Thread(target = connect_socket) #creat thread for socket
    socketThread.daemon = True #set daemon flag
    socketThread.start()
    SnakeApp().run

Solution

  • You should run the kivy main loop in the primary thread, and the socket listing in a secondary thread (reverse of your second try that didn't work).

    But it will leave your app hanging when you simply close it, because the secondary thread will keep it alive despite the primary thread being dead.

    The easiest solution to this problem is to start the secondary thread with a daemon = True flag, so it will be killed as soon as the primary thread is dead.