3

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()
2
  • Try to post a Minimal, Complete, and Verifiable example of the problem. Your code looks odd in that there are no threading constructs other than the lock, obviously you left some key information out. Commented Nov 2, 2016 at 16:29
  • The entire code resides here. Commented Nov 2, 2016 at 16:51

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I was thinking about an option where threads send requests to the main thread through a Queue or something of the likes. The the main htread responds with the input.
The suggestion I made above works, although it feels extremely hacky.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.