Author Ivan.Pozdeev
Recipients Ivan.Pozdeev, serhiy.storchaka, terry.reedy
Date 2018-05-02.19:38:38
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1525289918.68.0.682650639539.issue33257@psf.upfronthosting.co.za>
In-reply-to
Content
Here are the possible courses of action to fix this.

All require design changes, thus can be shot down on a whim. So I'll ask for advice and approval at python-dev first, to be sure that my efforts won't be scrapped.


First, some terminology I'll be using:
* A "(Tcl interpreter) call" (in quotes) is a sequence of interdependent calls into Tcl that a Tkinter routine makes in the course of its action.
* Outstanding "calls" are those from other threads that have not started yet and are currently waiting for the Tcl lock.
* A "downstream" "call" is a call made by a running PythonCmd's Python payload.
* Each call to PythonCmd has a "start" -- before releasing the Tcl lock -- and an "end" -- when it reacquires it to Tcl_SetObjResult() and return
* A PythonCmd is "active" when it's before its "start" and "end"


Now, the fix options proper:

* At the "end", rearrange the Tcl interpreter's stack frames so that the current PythonCmd's one is on top (effectively, make it look as if independent "calls" use independent Tcl stacks. Theoretically possible.)
    * Confirmed this to be impossible with Tcl's public API
* Prohibit other `PythonCmd's while one is already "active", except its "downstream" ones. Options:
    * At the "end", the old PythonCmd checks if there are others "calls" on top of it (will only happen if such "call" has another "active" PythonCmd on top: all other Tkinter routines hold the Tcl lock for their entire duration after the 33257 fix), wait if there are.
        * Problematic: this wait algorithm is biased against the old PythonCmd. Will lead to a potentially infinite wait if there are many threads making Tcl calls that result in PythonCmds.
    * Hold the Tcl lock for the entire duration of a PythonCmd. To allow "downstream" calls, make the Tcl lock reentrant.
        * Requires redesign of about two dozen functions in thread_*.c and pycond.h: there are only non-reentrant locks currently.
        * Behaviour change: wouldn't allow outstanding "calls" while a PythonCmd is "active". This change is transparent to Python code though.
    * Reuse the threaded versions of Tkapp_* routines: bind a nonthreaded interpreter to a thread and forward calls to it as events like in the threaded case
        * Problematic: visible behaviour change: `tk.call()`s would now hang without a running `mainloop()`. Currently, only event handlers don't fire.

Rejected options:
* The new PythonCmd somehow checks at "start" if another one is "active" and waits if it's not a descendant of it.
    * The new PythonCmd's Tcl interpreter frame has already been allocated when it gets control, so the old one cannot return before the new one in any case.
History
Date User Action Args
2018-05-02 19:38:38Ivan.Pozdeevsetrecipients: + Ivan.Pozdeev, terry.reedy, serhiy.storchaka
2018-05-02 19:38:38Ivan.Pozdeevsetmessageid: <1525289918.68.0.682650639539.issue33257@psf.upfronthosting.co.za>
2018-05-02 19:38:38Ivan.Pozdeevlinkissue33257 messages
2018-05-02 19:38:38Ivan.Pozdeevcreate