Reputation: 161
I have a background thread that occasionally needs keyboard input. However, the main thread also reads input from the keyboard. When I call input()
the main thread gets the input. I have tried using locks, but they do not work for me.
Main process (only part of the code):
def smth(aff):
af = aff
lock = threading.Lock()
print(lock)
Peer.setlock(lock)
while True:
lock.acquire(blocking=True, timeout=-1)
inp = input()
parse(inp)
lock.release()
Thread code:
global lock
def setlock(j):
print("Setting lock ", j)
global lock
lock = j
print("Lock status: ", lock.locked())
success = lock.acquire(blocking=True, timeout=-1)
print(success)
print("You are recieving a file, type y to confirm saving:")
print(lock)
if input() == "y":
path = ""
print("Input path:")
path = input()
if os.path.isfile(path):
print("File already exists. Type y to confirm:")
if not input()=="y":
return
handle = open(path, "wb")
filewriters[transferID] = filewg(handle, numberOfPackets)
filewriters[transferID].send(None)
lock.release()
print(lock)
The entire code resides here.
I just wrote another minimal example, and locks seem to work here: import threading
lock = threading.Lock()
def th():
while True:
lock.acquire(blocking=True, timeout=-1)
print("Thread prints ", input())
lock.release()
tic = threading.Thread(target=th)
tic.start()
while True:
lock.acquire(blocking=True, timeout=-1)
print("Main prints ", input())
lock.release()
Upvotes: 2
Views: 2367
Reputation: 1797
The immediate problem is that input()
in the main thread blocks and waits for input with the lock held. So no matter when your background thread tries to get input, the main thread is already holding the lock and waiting for input, and the first input goes to the main thread.
After that, the main thread calls release()
and then acquire()
again immediately. Unfortunately threading.Lock
makes no guarantees about fairness.. even if the background thread was waiting in acquire()
it's possible that the main thread's subsequent acquire()
will succeed first, "jumping the line" on the background thread.
Step back and look at what you are trying to do in the "big picture". You have one resource (the terminal input stream) that you are trying to direct to two different locations depending on the program execution context. I would think about a model where just one thread does the input()
but you look at global state to see what to do with it after that.
Upvotes: 2