Malloc corruption occurs when QAction signals are connected to methods wrapped with decorators, and the actions are not explicitly disconnected during widget disposal. This issue does not occur when using the functools.wraps decorator.
Python(28690,0x2081a9f00) malloc: Corruption of free object 0x14e19aa30: msizes 2/0 disagree Python(28690,0x2081a9f00) malloc: *** set a breakpoint in malloc_error_break to debug
Expected Behavior
- QAction signal connections should be automatically cleaned up when the widget is destroyed
- No malloc corruption should occur regardless of whether methods are decorated
Actual Behavior
- Malloc corruption occurs when destroying widgets with QAction signals connected to methods wrapped with custom decorators
- Error only occurs with decorators that don't use `functools.wraps`
- Explicit `action.triggered.disconnect()` is required as a workaround
Workaround
- Explicitly disconnect all QAction signals in the widget's dispose method (OR)
- Use functools.wraps for decorating QAction handler.
Reproducer Sample
A complete test case has been added that does the following modes for up to 20 iterations, where it tries to open and close a window widget with multiple QAction handlers with the following options. When it attempts to finally run the TestWithDecoratorAndDisconnect test type with the decorator pattern, it results in corruption in one of the iterations.
- TestWithFuncTools: Works correctly, no explicit disconnect needed.
- TestWithDecoratorAndDisconnect: Works with explicit disconnect workaround
- TestWithDecorator: Causes malloc corruption without explicit disconnect
Additional Notes:
- The issue only happens if there are more than 1 such QAction handler with the old decorator pattern.
- The decorator context's enter, exit events happen correctly as seen from the logs.