This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Python modules such as pyglet or pygame crash Python when tkinter message boxes are opened on MacOS.
Type: crash Stage: resolved
Components: macOS, Tkinter Versions: Python 3.10
process
Status: closed Resolution: third party
Dependencies: Superseder:
Assigned To: Nosy List: Marc.Culler, culler, ned.deily, remyrfouquette, ronaldoussoren
Priority: normal Keywords:

Created on 2022-01-29 18:48 by remyrfouquette, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue.py remyrfouquette, 2022-01-29 18:48 A short test I put together showing the issue.
Messages (12)
msg412093 - (view) Author: Remy Fouquette (remyrfouquette) Date: 2022-01-29 18:48
The same problem doesn't exist on Windows.
msg412309 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-01 21:18
Error output when running the script:

2022-02-01 22:15:32.213 Python[5468:5726153] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/d3/rc5nx4v12y96knh2px3bpqsc0000gn/T/org.python.python.savedState
2022-02-01 22:15:32.362 Python[5468:5726153] -[NSApplication macOSVersion]: unrecognized selector sent to instance 0x105624bc0
2022-02-01 22:15:32.367 Python[5468:5726153] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSApplication macOSVersion]: unrecognized selector sent to instance 0x105624bc0'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000018b4c01cc __exceptionPreprocess + 240
	1   libobjc.A.dylib                     0x000000018b2117b8 objc_exception_throw + 60
	2   CoreFoundation                      0x000000018b5531a0 -[NSObject(NSObject) __retain_OA] + 0
	3   CoreFoundation                      0x000000018b420360 ___forwarding___ + 1728
	4   CoreFoundation                      0x000000018b41fbe0 _CF_forwarding_prep_0 + 96
	5   libtk8.6.dylib                      0x0000000100940a1c GetRGBA + 64
	6   libtk8.6.dylib                      0x00000001009404a8 SetCGColorComponents + 140
	7   libtk8.6.dylib                      0x00000001009408e0 TkpGetColor + 544
	8   libtk8.6.dylib                      0x00000001008a2454 Tk_GetColor + 220
	9   libtk8.6.dylib                      0x0000000100895aa0 Tk_Get3DBorder + 204
	10  libtk8.6.dylib                      0x00000001008958ac Tk_Alloc3DBorderFromObj + 144
	11  libtk8.6.dylib                      0x00000001008a3810 DoObjConfig + 832
	12  libtk8.6.dylib                      0x00000001008a33cc Tk_InitOptions + 348
	13  libtk8.6.dylib                      0x00000001008a32c8 Tk_InitOptions + 88
	14  libtk8.6.dylib                      0x00000001008cacf0 CreateFrame + 1448
	15  libtk8.6.dylib                      0x00000001008cafe8 TkListCreateFrame + 156
	16  libtk8.6.dylib                      0x00000001008c3ec0 Initialize + 1848
	17  _tkinter.cpython-310-darwin.so      0x00000001008762d4 Tcl_AppInit + 92
	18  _tkinter.cpython-310-darwin.so      0x0000000100875f6c Tkapp_New + 548
	19  _tkinter.cpython-310-darwin.so      0x0000000100875d44 _tkinter_create_impl + 268
	20  _tkinter.cpython-310-darwin.so      0x000000010087597c _tkinter_create + 240
	21  Python                              0x000000010109b1f0 cfunction_vectorcall_FASTCALL + 88
	22  Python                              0x0000000101169f48 call_function + 132
	23  Python                              0x0000000101161fac _PyEval_EvalFrameDefault + 23072
	24  Python                              0x000000010115ad5c _PyEval_Vector + 360
	25  Python                              0x0000000101033dac _PyObject_FastCallDictTstate + 96
	26  Python                              0x00000001010c7cbc slot_tp_init + 196
	27  Python                              0x00000001010be950 type_call + 312
	28  Python                              0x0000000101033af4 _PyObject_MakeTpCall + 136
	29  Python                              0x000000010116a040 call_function + 380
	30  Python                              0x0000000101160a18 _PyEval_EvalFrameDefault + 17548
	31  Python                              0x000000010115ad5c _PyEval_Vector + 360
	32  Python                              0x0000000101169f48 call_function + 132
	33  Python                              0x0000000101160a18 _PyEval_EvalFrameDefault + 17548
	34  Python                              0x000000010115ad5c _PyEval_Vector + 360
	35  Python                              0x0000000101169f48 call_function + 132
	36  Python                              0x0000000101161404 _PyEval_EvalFrameDefault + 20088
	37  Python                              0x000000010115ad5c _PyEval_Vector + 360
	38  Python                              0x000000010115cb3c _PyEval_EvalFrameDefault + 1456
	39  Python                              0x000000010115ad5c _PyEval_Vector + 360
	40  Python                              0x0000000101169f48 call_function + 132
	41  Python                              0x0000000101160a18 _PyEval_EvalFrameDefault + 17548
	42  Python                              0x000000010115ad5c _PyEval_Vector + 360
	43  Python                              0x000000010115cb3c _PyEval_EvalFrameDefault + 1456
	44  Python                              0x000000010115ad5c _PyEval_Vector + 360
	45  Python                              0x000000010115cb3c _PyEval_EvalFrameDefault + 1456
	46  Python                              0x000000010115ad5c _PyEval_Vector + 360
	47  Python                              0x0000000101169f48 call_function + 132
	48  Python                              0x0000000101161404 _PyEval_EvalFrameDefault + 20088
	49  Python                              0x000000010115ad5c _PyEval_Vector + 360
	50  Python                              0x0000000101169f48 call_function + 132
	51  Python                              0x0000000101161404 _PyEval_EvalFrameDefault + 20088
	52  Python                              0x000000010115ad5c _PyEval_Vector + 360
	53  Python                              0x0000000101169f48 call_function + 132
	54  Python                              0x0000000101161404 _PyEval_EvalFrameDefault + 20088
	55  Python                              0x000000010115ad5c _PyEval_Vector + 360
	56  Python                              0x0000000101169f48 call_function + 132
	57  Python                              0x0000000101161fac _PyEval_EvalFrameDefault + 23072
	58  Python                              0x000000010115ad5c _PyEval_Vector + 360
	59  Python                              0x00000001011c52c8 pyrun_file + 308
	60  Python                              0x00000001011c4a0c _PyRun_SimpleFileObject + 336
	61  Python                              0x00000001011c4058 _PyRun_AnyFileObject + 216
	62  Python                              0x00000001011f0280 pymain_run_file_obj + 180
	63  Python                              0x00000001011ef920 pymain_run_file + 72
	64  Python                              0x00000001011eef08 pymain_run_python + 300
	65  Python                              0x00000001011eed9c Py_RunMain + 24
	66  Python                              0x00000001011f0428 pymain_main + 56
	67  Python                              0x00000001011f06ec Py_BytesMain + 40
	68  dyld                                0x00000001005bd0f4 start + 520
)
libc++abi: terminating with uncaught exception of type NSException
msg412310 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-01 21:19
The last bit of the call stack according to lldb:

* thread #2, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x000000018b3419b8 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x000000018b374eb0 libsystem_pthread.dylib`pthread_kill + 288
    frame #2: 0x000000018b2b2314 libsystem_c.dylib`abort + 164
    frame #3: 0x000000018b331b50 libc++abi.dylib`abort_message + 132
    frame #4: 0x000000018b322f64 libc++abi.dylib`demangling_terminate_handler() + 332
    frame #5: 0x000000018b21a140 libobjc.A.dylib`_objc_terminate() + 144
    frame #6: 0x000000018b330ee4 libc++abi.dylib`std::__terminate(void (*)()) + 20
  * frame #7: 0x000000018b333c5c libc++abi.dylib`__cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 36
    frame #8: 0x000000018b333c08 libc++abi.dylib`__cxa_throw + 140
    frame #9: 0x000000018b2118dc libobjc.A.dylib`objc_exception_throw + 352
    frame #10: 0x000000018b5531a0 CoreFoundation`-[NSObject(NSObject) doesNotRecognizeSelector:] + 144
    frame #11: 0x000000018b420360 CoreFoundation`___forwarding___ + 1728
    frame #12: 0x000000018b41fbe0 CoreFoundation`_CF_forwarding_prep_0 + 96
    frame #13: 0x0000000102388a1c libtk8.6.dylib`GetRGBA + 64
    frame #14: 0x00000001023884a8 libtk8.6.dylib`SetCGColorComponents + 140
    frame #15: 0x00000001023888e0 libtk8.6.dylib`TkpGetColor + 544
    frame #16: 0x00000001022ea454 libtk8.6.dylib`Tk_GetColor + 220
    frame #17: 0x00000001022ddaa0 libtk8.6.dylib`Tk_Get3DBorder + 204
    frame #18: 0x00000001022dd8ac libtk8.6.dylib`Tk_Alloc3DBorderFromObj + 144
    frame #19: 0x00000001022eb810 libtk8.6.dylib`DoObjConfig + 832
    frame #20: 0x00000001022eb3cc libtk8.6.dylib`Tk_InitOptions + 348
    frame #21: 0x00000001022eb2c8 libtk8.6.dylib`Tk_InitOptions + 88
    frame #22: 0x0000000102312cf0 libtk8.6.dylib`CreateFrame + 1448
    frame #23: 0x0000000102312fe8 libtk8.6.dylib`TkListCreateFrame + 156
    frame #24: 0x000000010230bec0 libtk8.6.dylib`Initialize + 1848
    frame #25: 0x000000010026a2d4 _tkinter.cpython-310-darwin.so`Tcl_AppInit + 92
    frame #26: 0x0000000100269f6c _tkinter.cpython-310-darwin.so`Tkapp_New + 548
    frame #27: 0x0000000100269d44 _tkinter.cpython-310-darwin.so`_tkinter_create_impl + 268
    frame #28: 0x000000010026997c _tkinter.cpython-310-darwin.so`_tkinter_create + 240
    frame #29: 0x0000000100bf71f0 Python`cfunction_vectorcall_FASTCALL + 88
msg412311 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-01 21:27
If I interpret the information I posted earlier correctly this is a bug in Tkinter, it calls a non-existing Objecive-C method (``-[NSApplication macOSVersion]``) and that results in an uncaught Objective-C exception and hence an abort().

BTW. All of this is using python 3.10.2 using the installer on python.org.
msg412312 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2022-02-01 21:30
> If I interpret the information I posted earlier correctly this is a bug in Tkinter [...]

Tkinter? Or Tk itself?
msg412344 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-02 08:38
Oops, sorry: In Tk itself.
msg412349 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-02 10:11
I've done some more research and this is an integration issue between pyglet and Tk. In particular:

* Both pyglet and Tk use AppKit to implement their GUI
* AppKit uses an NSApplication class, and in particular a singleton instance of that class, to represent the application, which will get instantiated during application startup
* The Tk library uses a sublclass of NSApplication with additional functionality (TkApplication).
* When pyglet is started first the NSApplication singleton is an instance of NSApplication and not of TkApplication, but Tk's implementation assumes that the singleton is an instance of TkApplicationo.

A workaround for this issue is to make sure Tk is initialised before initialising pyglet. For example using this code at the start of the script: "from tkinter import Tk; root = Tk()"


There's not much we can do about this in CPython, other than maybe filing an issue with the Tk project about this. I haven't looked at the Tk codebase and there cannot tell how hard it would be for then to avoid a dependency on TkApplication as a separate class (for example by implementing the additional functionality they need in a category on NSApplication).
msg412392 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2022-02-02 19:54
Thanks for looking into this, Ronald. Before we close this as a Python issue, perhaps Marc might have a suggestion on what should be done here from a Tk perspective.
msg412399 - (view) Author: Marc Culler (Marc.Culler) * Date: 2022-02-02 20:36
The TKApplication class is a subclass of NSApplication which adds both
attributes and methods.  Those are used throughout the macOS port of Tk,
and as Ronald says, the unique instance of NSApplication in Tk is actually
a TKApplication.  Every macOS Application must have a unique NSApplication
object which is referenced by the global variable NSApp.  The TKApplication
subclass was part of the first Cocoa port of Tk, long before I became
involved, and it may have even been there in the Carbon days.  Subclassing
NSApplication appears to be something that Apple expects.

I don't know enough about Categories to understand how they could be used
to solve this problem.  Do they somehow make it possible to add new methods
and attributes to an existing NSApplication object at runtime?  I have
always thought of them as being syntactical in nature, as opposed to
allowing runtime modifications of an object's class after the object has
been instantiated.  But I am not an expert on Categories by any means.

- Marc

On Wed, Feb 2, 2022 at 1:54 PM Ned Deily <report@bugs.python.org> wrote:

>
> Ned Deily <nad@python.org> added the comment:
>
> Thanks for looking into this, Ronald. Before we close this as a Python
> issue, perhaps Marc might have a suggestion on what should be done here
> from a Tk perspective.
>
> ----------
> nosy: +culler
> status: pending -> open
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue46573>
> _______________________________________
>
msg412423 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-03 07:37
Categories make it possible to add methods to an existing class, but not new attributes.  The latter shouldn't be a problem in principle for an NSApplication subclass because only a single instance of the application class will get created and you may as well use global variables for those.

In some sense categories are syntactic sugar for monkey patching existing classes, commonly used to add convenience methods to Cocoa classes.
msg412425 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2022-02-03 08:29
Something I forgot to mention: I don't think this is a bug in Tk now that I've looked into this more deeply. 

The integration problem between Tk and other users of the Cocoa event loop is unfortunate but not a bug.
msg412469 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2022-02-03 21:05
Thanks, Marc and Ronald, for the analysis.

And thanks for bringing up the issue, Remy. Perhaps you can verify that Ronald's suggestion of importing and launching Tk before calling pyglet or pygame works for you and, if so, follow up with those projects to, if nothing else, document that requirement for their users on macOS (I would guess it wouldn't hurt on other platforms as well but I've guessed wrong before). In any case, I'm closing this issue now.
History
Date User Action Args
2022-04-11 14:59:55adminsetgithub: 90731
2022-02-03 21:05:49ned.deilysetstatus: open -> closed

messages: + msg412469
2022-02-03 08:29:56ronaldoussorensetmessages: + msg412425
2022-02-03 07:37:23ronaldoussorensetmessages: + msg412423
2022-02-02 20:36:04Marc.Cullersetnosy: + Marc.Culler
messages: + msg412399
2022-02-02 19:54:21ned.deilysetstatus: pending -> open
nosy: + culler
messages: + msg412392

2022-02-02 10:11:45ronaldoussorensetstatus: open -> pending
resolution: third party
messages: + msg412349

stage: resolved
2022-02-02 08:38:22ronaldoussorensetmessages: + msg412344
2022-02-01 21:30:45ned.deilysetmessages: + msg412312
2022-02-01 21:27:28ronaldoussorensetmessages: + msg412311
components: + Tkinter
2022-02-01 21:19:37ronaldoussorensetmessages: + msg412310
2022-02-01 21:18:13ronaldoussorensetmessages: + msg412309
2022-01-29 18:48:13remyrfouquettecreate