TypeError: arguments did not match any overloaded call QMutexLocker
Exception in callback _ProactorReadPipeTransport._loop_reading(<_OverlappedF...hed result=10>)
handle: <Handle _ProactorReadPipeTransport._loop_reading(<_OverlappedF...hed result=10>)>
Traceback (most recent call last):
File "asyncio\events.py", line 80, in _run
File "asyncio\proactor_events.py", line 301, in _loop_reading
File "qasync\_windows.py", line 86, in recv_into
TypeError: arguments did not match any overloaded call:
QMutexLocker(mutex: Optional[QMutex]): argument 1 has unexpected type 'QMutexLocker'
QMutexLocker(mutex: Optional[QRecursiveMutex]): argument 1 has unexpected type 'QMutexLocker'
Traceback (most recent call last):
File "qasync\_windows.py", line 196, in run
File "qasync\_windows.py", line 69, in select
File "qasync\_windows.py", line 149, in _poll
TypeError: arguments did not match any overloaded call:
QMutexLocker(mutex: Optional[QMutex]): argument 1 has unexpected type 'QMutexLocker'
QMutexLocker(mutex: Optional[QRecursiveMutex]): argument 1 has unexpected type 'QMutexLocker'
Is this project dead?
I think the maintainers typically reply to say it's not dead but nothing ever gets merged so 🤷
See:
https://github.com/CabbageDevelopment/qasync/issues/119#issuecomment-2139643654
We are also seeing this on the latest release (in the context of https://github.com/m-labs/artiq on Windows):
File "C:\Users\LabUser\AppData\Local\Programs\Python\Python311\Lib\asyncio\streams.py", line 332, in write
self._transport.write(data)
File "C:\Users\LabUser\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 365, in write
self._loop_writing(data=bytes(data))
File "C:\Users\LabUser\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 401, in _loop_writing
self._write_fut = self._loop._proactor.send(self._sock, data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\LabUser\AppData\Local\pypoetry\Cache\virtualenvs\artiq-oitg-UIB2HjkM-py3.11\Lib\site-packages\qasync\_windows.py", line 102, in send
with QtCore.QMutexLocker(self._lock):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: arguments did not match any overloaded call:
QMutexLocker(mutex: Optional[QMutex]): argument 1 has unexpected type 'QMutexLocker'
QMutexLocker(mutex: Optional[QRecursiveMutex]): argument 1 has unexpected type 'QMutexLocker'
I strongly suspect that this involves memory corruption or lifetime management issues, as self._lock is obviously not itself a QMutexLocker.
@blluv: Do you have a stand-alone reproducer for this?
It would be interesting to see whether this also occurs with PySide instead of PyQt.
May not be totally related, but I was getting errors like this when using the QApplication from Pyside instead of qasync. Switching to the qasync one fixed the async crashes I was getting.
This was after determining that these crashes were memory faults by looking at the windows event viewer. For future readers, if you get unexplainable crashes from PyQT / Pyside, add this to your code to get the traceback.
import faulthandler
faulthandler.enable()
May not be totally related, but I was getting errors like this when using the QApplication from Pyside instead of qasync. Switching to the qasync one fixed the async crashes I was getting.
Huh – isn't that just a re-exported version of the underlying PyQt/PySide one, though?
It seems you are correct. Nevertheless my application hasn't had a random crash from a thread since I made that change. Seems preposterous.
And it wasn't maybe the auto-selelction causing you to switch to a different (Py)Qt library?
I got the similar exception as above: (It was just some simple asyncio task running at background that uses aiohttp and updates the UI.)
Traceback (most recent call last):
File "{proj_path}\.venv\Lib\site-packages\qasync\_windows.py", line 196, in run
events = self.__proactor.select(0.01)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "{proj_path}\.venv\Lib\site-packages\qasync\_windows.py", line 69, in select
self._poll(timeout)
File "{proj_path}\.venv\Lib\site-packages\qasync\_windows.py", line 149, in _poll
with QtCore.QMutexLocker(self._lock):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: arguments did not match any overloaded call:
QMutexLocker(mutex: QMutex): argument 1 has unexpected type 'QMutexLocker'
QMutexLocker(mutex: QRecursiveMutex): argument 1 has unexpected type 'QMutexLocker'
The exception appears to be a type mismatch caught at runtime ? The exception happens out of nowhere, cannot determine if my code or qasync code or other triggers that.
The following "Application Error" found from windows event viewer seems related:
Faulting application name: python.exe,version: 3.11.4150.1013,time stamp: 0x64801a28 Faulting module name: Qt6Core.dll,version: 6.4.3.0,time stamp: 0x640c8ac4 exception code: 0xc0000409 Fault offset: 0x0000000000011918 Faulting application path: {user path}\AppData\Local\Programs\Python\Python311\python.exe Faulting module path : {proj_path}.venv\Lib\site-packages\PyQt6\Qt6\bin\Qt6Core.dll
from ms community or a stackoverflow question, the exception code seems to be a memory fault
The error code 0xc0000409 indicates a stack buffer overflow, which can occur due to various reasons such as a corrupt file or memory issue.
0xc0000409 means STATUS_STACK_BUFFER_OVERRUN.
In other words, something in your program is writing past the current stack frame, corrupting data on the stack. The program has detected this and rather than let it continue, has thrown an exception.
looks like "memory fault in official Qt6Core.dll" leads to "Type mismatch exception in qasync _windows.py", but self._lock is QtCore.QMutex() instance, how comes that memory fault (in c++'s view?) interpreted as a type mismatch exception (in python's view?) ?
This is not a qasync bug. I was able to reproduce it on linux by pattern matching what Qasync was doing
import threading
import time
from PyQt6.QtCore import QMutex, QMutexLocker, QCoreApplication
import sys
class SharedResource:
def __init__(self):
self._lock = QMutex()
print(f"Initial: self._lock is {type(self._lock).__name__} at {id(self._lock)}")
def method_a(self):
"""Called from thread A"""
for i in range(10000):
try:
# This is the pattern used in qasync
with QMutexLocker(self._lock):
pass
except TypeError as e:
print(f"Thread A failed at iteration {i}: {e}")
print(f"self._lock is now {type(self._lock).__name__} at {id(self._lock)}")
return False
return True
def method_b(self):
"""Called from thread B (main thread)"""
for i in range(10000):
try:
with QMutexLocker(self._lock):
pass
except TypeError as e:
print(f"Thread B failed at iteration {i}: {e}")
print(f"self._lock is now {type(self._lock).__name__} at {id(self._lock)}")
return False
return True
def main():
app = QCoreApplication(sys.argv)
resource = SharedResource()
# Start thread A
thread_a = threading.Thread(target=resource.method_a)
thread_a.start()
# Run method_b in main thread
success_b = resource.method_b()
# Wait for thread A
thread_a.join()
print(f"\nFinal: self._lock is {type(resource._lock).__name__} at {id(resource._lock)}")
if not success_b:
print("\nBUG REPRODUCED: QMutex was replaced with QMutexLocker!")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
gives
python min.py
Initial: self._lock is QMutex at 139328410447568
Exception in thread Thread-1 (method_a):
Traceback (most recent call last):
File "/usr/lib/python3.12/threading.py", line 1073, in bootstrapinner
self.run()
File "/usr/lib/python3.12/threading.py", line 1010, in run
self._target(*self._args, **self._kwargs)
File "/home/danielrh/dev/pyqtbug/min.py", line 22, in method_a
with QMutexLocker(self._lock):
^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: wrapped C/C++ object of type QMutex has been deleted
Segmentation fault (core dumped)
This was PyQt6 version: 6.6.1 or 6.9.1 Python version: 3.12.3 (main, Jun 18 2025, 17:59:45) [GCC 13.3.0]
the same script has more trouble on Python 3.11.9 with PyQt6 version 6.9.1 for some reason
The stack trace is
Thread 3 "python" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff31fe6c0 (LWP 340823)]
Downloading source file /usr/src/python3.12-3.12.3-1ubuntu0.7/build-static/../Objects/weakrefobject.c
clear_weakref (self=0x7ffff7398e30) at ../Objects/weakrefobject.c:60
warning: 60 ../Objects/weakrefobject.c: No such file or directory
--Type <RET> for more, q to quit, c to continue without paging--
#0 clear_weakref (self=0x7ffff7398e30) at ../Objects/weakrefobject.c:60
#1 0x00000000005c8ce4 in PyObject_ClearWeakRefs (object=<optimized out>)
at ../Objects/weakrefobject.c:952
#2 0x000000000059ea58 in subtype_dealloc (self=0x7ffff7398cd0)
at ../Objects/typeobject.c:1974
#3 0x00000000005e0105 in _PyEval_EvalFrameDefault (tstate=<optimized out>,
frame=<optimized out>, throwflag=<optimized out>)
at Python/bytecodes.c:2731
#4 0x000000000054cb32 in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=1,
args=0x7ffff31fde18, callable=0x7ffff749d580, tstate=0xd8f0b0)
at ../Include/internal/pycore_call.h:92
#5 method_vectorcall (method=<optimized out>,
args=0xb49140 <_PyRuntime+76288>, nargsf=<optimized out>, kwnames=0x0)
at ../Objects/classobject.c:69
#6 0x00000000006f80dc in thread_run (boot_raw=0xd8f080)
at ../Modules/_threadmodule.c:1114
#7 0x00000000006b931c in pythread_wrapper (arg=<optimized out>)
at ../Python/thread_pthread.h:237
#8 0x00007ffff7c9caa4 in start_thread (arg=<optimized out>)
at ./nptl/pthread_create.c:447
#9 0x00007ffff7d29c3c in clone3 ()
Possibly this sequence of events:
Thread 1 Thread 2
-------- --------
with QMutexLocker(mutex): with QMutexLocker(mutex):
# Creates C++ QMutexLocker # Creates C++ QMutexLocker
# Increments wrapper refcount # Race condition here!
... ...
# __exit__ called # __exit__ called
# Decrements refcount # Decrements refcount
# INCORRECTLY frees QMutex! # Tries to use freed memory
# Python GC → SEGFAULT
I have a much smaller repro case:
import threading
from PyQt6.QtCore import QMutex, QMutexLocker, QCoreApplication
import sys
import faulthandler
faulthandler.enable()
app = QCoreApplication(sys.argv)
mutex = QMutex()
def worker():
for i in range(10000):
with QMutexLocker(mutex): # Crashes here
pass
thread1 = threading.Thread(target=worker)
thread2 = threading.Thread(target=worker)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
You can import this file at the beginning of your main and it should fix the problem by patching in native python threading.Lock() instead of using PyQt6's broken lock.
Perhaps developers of qasync can consider patching this in until Riverbank Computing fixes PyQt6
or avoiding the QMutexLocker by merging https://github.com/danielrh/qasync/commit/b497a153378bc948458574e3f595711c49347f31
@danielrh Thanks, this is great! I did need to significantly increase the loop iteration count in your reproduction case (Python 3.12/Windows 11), but that's pretty cut and dry. When starting to look into this previously, avoiding QMutexLocker did seem to fix it, but I was never quite sure since I didn't have a self-contained test case yet. Sadly, I don't have commit access here, but I'll immediately roll out https://github.com/danielrh/qasync/commit/b497a153378bc948458574e3f595711c49347f31 in the application used across my research group.
Fixed in https://github.com/CabbageDevelopment/qasync/pull/151