1

My Code is:

class Client(DirectObject, object):

'''
Clientclass. This class processes the keys which the user presses to the host and gets the data
from the host, which are to be set in a dummy version of the model
'''

seed= ""
id = None

def __init__(self, ip):
    '''
    This is the  constructor. It creates the ShowBase an starts both the process which processes the keys and the process 
    which takes in data from the host
    param: ip ip is a float which contains the ip adress of the host

    '''
    logging.getLogger(__name__).info("Clientobjekt erstellt")
    self.makw = mouseAndKeyWrapper.MouseAndKeyWrapper()
    time.sleep(5)      
    from modules.logic import game
    self.cprocess = threading.Thread(target = Client.workAsClient, args = (ip,self.makw))
    self.cprocess.start()
    time.sleep(5)
    while True:
        if Client.seed != "":
            break               
    game.seed = Client.seed
    game.initGame()
    game.initGameInstance()    
    game.start()    

    self.workShowBase()  
    game.myShowBase.run()



def workShowBase(self):

    '''
    workShowBase defines how to change values in keydict when keys are pressed and
    starts ShowBase process
    '''
    from modules.logic import game
    logging.getLogger(__name__).info("Showbase is working")
    game.myShowBase.accept("w", self.makw.setKeys, ["w",1])
    game.myShowBase.accept("a", self.makw.setKeys, ["a",1])
    game.myShowBase.accept("s", self.makw.setKeys, ["s",1])
    game.myShowBase.accept("d", self.makw.setKeys, ["d",1])
    game.myShowBase.accept("space", self.makw.setKeys, ["space",1])
    game.myShowBase.accept("w-up", self.makw.setKeys, ["w",0])
    game.myShowBase.accept("a-up", self.makw.setKeys, ["a",0])
    game.myShowBase.accept("s-up", self.makw.setKeys, ["s",0])
    game.myShowBase.accept("d-up", self.makw.setKeys, ["d",0])
    game.myShowBase.accept("space-up", self.makw.setKeys, ["space",0])
    #game.myShowBase.accept("mouse1",self.makw.setKeys,["mouse",1])
    #game.myShowBase.accept("mouse1-up",self.makw.setKeys,["mouse",0])





@staticmethod  
def workAsClient(ip, makw):
    '''
    This method contains the client thread, that is, the thread which sends data to the host and
    receives data from it - for this reason it has to be static
    param: ip ip is a float which contains the ip adress of the host
    '''
    logging.getLogger(__name__).info("Clientendlosschleife gestartet")
    from modules.logic import game
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect((ip, 50001)) 
    seedSend = s.recv(4096)
    Client.seed =loads(seedSend)
    ID = s.recv(4096)
    Client.id = loads(ID)      
    makw.id = id
    keyThread = threading.Thread(target =Client.sendData, args = (makw,s))
    print("threadmade")
    keyThread.start()
    print("started")

@staticmethod    
def sendData(makw, sock):
    print("method")     
    while True:
        print("loop")
        dictToSend = dumps(makw,2)
        print("dumped")
        sock.sendall(dictToSend)
        print("sent")

That does work fine.

However, if I omitt "time.sleep(5)" in the constructor, the thread which calls sendData is never ever made, let alone be started. How can that be? Showbase technically should not interfere, being in another process! Can I fix this?

user1862770
  • 307
  • 1
  • 4
  • 13

1 Answers1

1

You should avoid using full active waiting that may consume all the resources letting no chance for other threads to work.

So you may better try :

while True:
        if Client.seed != "":
            break
        time.sleep(10)

Indeed your secondary thread is launched but if all processing is consumed by your main thread in its infinite loop it will never have a chance to work, then never providing the seed for which the main thread is waiting => deadlock

When you use sleep(5) you give a chance to the secondary thread to be scheduled and to produce the seed; then when latter the main thread is rescheduled it finds the seed, continues working and all is going as expected.

But your workaround is very brittle because you have no guarantee that during the sleep of the main thread the other one will be scheduled.

It works now in your development environment but may break later in production in another context.

Pragmateek
  • 13,174
  • 9
  • 74
  • 108
  • Ooops it seems the "But this workaround..." was not correctly interpreted ;) : "this" is your original workaround; I've edited my answer to make it clear. My code sample is the correct way to go, not a workaround :) – Pragmateek Jan 12 '13 at 13:56
  • Well...the thing is, with what I did it worked in 20% of the cases. With your solution it works out in 80% of the cases but there is still 20% of the cases where I get the same mistake as before and I have no idea why. Have you? – user1862770 Jan 12 '13 at 19:58
  • Please check exactly where it is blocked; if it's on the "recv" then you have another issue. Who is sending the seed to your server? – Pragmateek Jan 12 '13 at 23:43
  • It is SOMETIMES blocked after s.recv and SOMETIMES right after print("started"). The recv works always, however, as I am using that data to get a picture. If that did not work, I would have no picture whatsoever, and I definitely have one. – user1862770 Jan 13 '13 at 10:52
  • Why does the "sendData" is looping forever? If I understand correctly your code it should do a one-shot task and end immediately... – Pragmateek Jan 13 '13 at 12:31