Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on MacOS 12.6 (M1) when pressing caps_lock #510

Open
perroboc opened this issue Oct 24, 2022 · 9 comments
Open

Crash on MacOS 12.6 (M1) when pressing caps_lock #510

perroboc opened this issue Oct 24, 2022 · 9 comments

Comments

@perroboc
Copy link

perroboc commented Oct 24, 2022

Description
Keyboard listening on MacOS (M1 Pro) works and logs all keys. But it crashes after pressing Caps Lock

Platform and pynput version
macOS Monterey (12.6), M1 Pro. Pynput 1.7.6, Pyside6 6.4.0, Python 3.10. I'm also using a Latin American keyboard layout.

To Reproduce
https://github.com/alvaromunoz/pynput-macos-issues/blob/ba17e4b83f1eb239454d73ba96adf7f5fe71673b/caps_lock.py

import sys

from PySide6 import (
    QtWidgets,
)

from pynput import keyboard

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Listener Demo 1")

        central_widget = QtWidgets.QWidget()

        layout = QtWidgets.QVBoxLayout()
        central_widget.setLayout(layout)

        label_description = QtWidgets.QLabel("Press Caps lock to crash.")
        layout.addWidget(label_description)

        label = QtWidgets.QLabel("Press any key")
        layout.addWidget(label)

        def on_press(key):
            label.setText("You pressed {0}".format(key))

        def on_release(key):
            label.setText("You released {0}".format(key))
        
        listener = keyboard.Listener(
            on_press=on_press,
            on_release=on_release)
        listener.start()

        self.setCentralWidget(central_widget)

app = QtWidgets.QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec()

OUTPUT:

zsh: trace trap
@moses-palmer
Copy link
Owner

Thank you for your report.

From what I have gathered, zsh report this error on unhandled signals, in this SIGTRAP. This should not happen in the library code nor in the Python runtime code. I suspect that the culprit is a native library, perhaps some part of pyobjc.

Perhaps adding some print statements in Listener._event_to_key would provide some hints as to where the error occurs?

@perroboc
Copy link
Author

perroboc commented Nov 29, 2022 via email

@moses-palmer
Copy link
Owner

That's peculiar—a SIGTRAP because of a missing delay?

Would you mind posting a diff that fixes the code above?

@perroboc
Copy link
Author

perroboc commented Dec 1, 2022

I’d LOVE to, but I haven’t found a fix yet. Further tests show that even holding the button does NOT fix the issue, sorry.

Here's a video showing the difference the behavior when holding the key or not:

Is there any way to read the SIGTRAP dumps?

@HaujetZhao
Copy link

HaujetZhao commented Jun 7, 2023

MacOS uses tap Capslock to switch InputMethod of non-English language, click it get a keycode 0xFF, I think it's a media-key stands for switching IME. Hold capslock triggers the true capslock keycode.

Can be configured in: Settings > Keyboard > IME

@hgiesel
Copy link

hgiesel commented Feb 11, 2024

Just encountered this issue again. Did anybody find a solution to this, or the cause of the SIGTRAP?

@Darcy-C
Copy link

Darcy-C commented Feb 14, 2024

I do believe this problem is related to IME.

For whatever reason, I found when I comment the line, the problem disappears.

_EVENTS = (
    Quartz.CGEventMaskBit(Quartz.kCGEventKeyDown) |
    Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) |
    Quartz.CGEventMaskBit(Quartz.kCGEventFlagsChanged) 
    | Quartz.CGEventMaskBit(Quartz.NSSystemDefined) # 👈 comment it if you do not want the media keys
)

But Commenting this line will also lead to loss of the ability to listen to the system defined key.


I am trying to use faulthandler to locate the line which triggered the unwanted exit, and it shows the following tracebacks.

Python error: Aborted

Thread 0x0000000175903000 (most recent call first):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pynput/_util/darwin.py", line 215 in _run
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pynput/keyboard/_darwin.py", line 253 in _run
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pynput/_util/__init__.py", line 210 in run
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016 in _bootstrap_inner
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 973 in _bootstrap

which points to the line on my machine

result = Quartz.CFRunLoopRunInMode(
                        Quartz.kCFRunLoopDefaultMode, 1, False)

It seems like the problem has not happened inside python codebase. Just like moses-palmer said, It's related to pyobjc.

@hgiesel
Copy link

hgiesel commented Feb 14, 2024

Maybe because NSSystemDefined is deprecated?

@huynguyengl99
Copy link

huynguyengl99 commented Nov 5, 2024

Based on the above suggestion, here is my temporary fix: removing (Quartz.CGEventMaskBit(Quartz.NSSystemDefined)). This can be helpful for anyone looking for a quick solution. However, there is a trade-off:

But Commenting this line will also lead to loss of the ability to listen to the system defined key.

from pynput import keyboard

if platform.system() == 'Darwin':
    import Quartz
    darwin_events = (
        Quartz.CGEventMaskBit(Quartz.kCGEventKeyDown) |
        Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) |
        Quartz.CGEventMaskBit(Quartz.kCGEventFlagsChanged)
    )

    keyboard._darwin.Listener._EVENTS = darwin_events

Hope someone can resolve this problem in future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants