pythonmacoskeyboardpsychopypsychtoolbox

PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/


I'm using the Psychopy module in Python. My code calls waitKeys(...) to get keypresses and reaction times. 90% of the time it works perfectly, but occasionally when I launch it I get this (exactly this, not an infinite repetition):

PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/...!
PTB-WARNING: This is likely a security measure, e.g., to protect some active password entry field.
PTB-WARNING: Please identify and quit the offending application. E.g., some versions of Firefox are known to cause such problems...
PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/...!
PTB-WARNING: This is likely a security measure, e.g., to protect some active password entry field.
PTB-WARNING: Please identify and quit the offending application. E.g., some versions of Firefox are known to cause such problems...
PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/...!
PTB-WARNING: This is likely a security measure, e.g., to protect some active password entry field.
PTB-WARNING: Please identify and quit the offending application. E.g., some versions of Firefox are known to cause such problems...
PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/...!
PTB-WARNING: This is likely a security measure, e.g., to protect some active password entry field.
PTB-WARNING: Please identify and quit the offending application. E.g., some versions of Firefox are known to cause such problems...
PTB-WARNING: During PsychHID invocation: Some other running application is preventing me from accessing the keyboard/keypad/mouse/...!
PTB-WARNING: This is likely a security measure, e.g., to protect some active password entry field.
PTB-WARNING: Please identify and quit the offending application. E.g., some versions of Firefox are known to cause such problems...

and not surprisingly it does not respond to any of my keystrokes, only to control-C.

I am only running Terminal (to launch the script), Xcode (to edit the python script), and Safari with only a couple of vanilla websites open (stackoverlow.com, discourse.psychopy.org, and google.com for searching). The only way I can stop this behaviour is by logging out then logging back in. Closing the Terminal window and opening a new one doesn't fix it. Quitting from Terminal and relaunching it doesn't fix it. Quitting from all running apps then relaunching Terminal doesn't fix it.

Sometimes when it happens, I had control-C'd out of the app just prior to this happening on the next launch. So perhaps Psychopy is leaving some orphaned thread still running in the background, from that prior invocation of the script, and that thread hasn't relinquished its claim on the keyboard? How could I find out? And how can I address that in my code?

Here's the relevant code:

**from** psychopy **import** prefs
prefs.hardware['audioLib'] = ['PTB']  # Prepare to use the right audio backend before importing sound
latencyMode = 4    # For PTB. 0, 1, 2, 3, 4
prefs.hardware['audioLatencyMode'] = [str(latencyMode)]
from psychopy.sound.backend_ptb **import** SoundPTB
from psychopy.hardware **import** keyboard
kb = keyboard.Keyboard() # Set up a keyboard device
targetAudio = SoundPTB(listFiles[thisAudioIndex])
targetAudio.play()
 keys = kb.waitKeys(keyList = ["return", "space", "down", "right"],
                           waitRelease=False)
targetAudio.stop()

2017 MacBook Pro, using the inbuilt keyboard. macOS 11.4, Python 3.8. I also posted this on discourse.psychopy.org


Solution

  • Solved (kind of!).

    For UI reasons, I stop keys typed during the experiment from being echoed to the screen (otherwise the screen gets full of random junk). I do this by sending stty -echo to the parent shell.

    But when exiting from the program (for any reason) I need to undo this by sending stty echo. So I set up an exit handler:

    def onExit():
        """Restore keystroke echo when we exit"""
        os.system('stty echo')
    

    However if the user types control-C then such an exit handler would not be executed, so I also have to trap control-C:

    def captureControl_C(signum, frame):
        """If user types control-c, restore keystroke echo before quitting"""
        # Restore the original signal handler, otherwise evil things will happen
        # if CTRL+C is pressed while we are already here, e.g. "c" key bounced
        signal.signal(signal.SIGINT, originalSigintHandler)
        os.system('stty echo')
        raise KeyboardInterrupt # So we still see the stack trace on the screen
    

    See here for details.

    And this brings us to the problem. I connect up the above exit handler and trap with the following 3 lines in __main__:

    os.system('stty -echo') # Stop any echo of keystrokes to the Terminal window.
    atexit.register(onExit) # Restore keyboard echo when quitting
    #
    # BUT if user types control-c, then restore keyboard echo!
    # Otherwise the Terminal window looks unresponsive.
    #
    originalSigintHandler = signal.signal(signal.SIGINT, captureControl_C)
    

    When those 3 lines are in __main__ then everything works perfectly. But then I shifted them into a function initialSetup() which is called from main. In doing that, of course I had to precede them with

    global originalSigintHandler # So that captureControl_C() can see it
    

    Moving the crucial 3 lines into initialSetup() caused subsequent calls to waitKeys() to hang with all those warnings in my initial post. Moving them back to __main__ fixed it.

    I'd be delighted if anybody could explain why.