Tk Source Code

View Ticket
Bounty program for improvements to Tcl and certain Tcl packages.
10:09 Closed ticket [8ebed330]: doing some Tk inside of several threads crashes plus 6 other changes artifact: 696f90a1 user: jan.nijtmans
Fix [8ebed330ed]: doing some Tk inside of several threads crashes check-in: b101d484 user: jan.nijtmans tags: core-8-6-branch
05:40 Ticket [8ebed330] doing some Tk inside of several threads crashes status still Open with 3 other changes artifact: a74c4b59 user: jan.nijtmans
23:03 Ticket [8ebed330]: 3 changes artifact: 10399b4a user: chw
09:48 Ticket [8ebed330]: 3 changes artifact: b0106a29 user: anonymous
09:39 Ticket [8ebed330]: 3 changes artifact: bb893b84 user: chw
09:33 Add attachment tkUnixRFont.c.diff to ticket [8ebed330] artifact: a7886b3a user: chw
09:33 Ticket [8ebed330] doing some Tk inside of several threads crashes status still Open with 3 other changes artifact: f15df4af user: chw
06:46 Ticket [8ebed330]: 3 changes artifact: 641e593b user: chw
21:01 New ticket [8ebed330]. artifact: 0c26f568 user: anonymous

Ticket UUID: 8ebed330edc670d54c754a8c716f843ee451452d
Title: doing some Tk inside of several threads crashes
Type: Bug Version: 8.6.9 and .11
Submitter: anonymous Created on: 2021-09-18 21:01:09
Subsystem: 67. Unix Window Operations Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2021-10-14 10:09:44
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2021-10-14 10:09:44
Running this on ubuntu and other linux systems causes several types of failures as shown in the log below.

It does not crash every time, and so was run 1000 times in a bash script. It can also fail simply by doing a package require Tk, but far less frequently.

package require Thread

set script {
    proc putz {arg color } {
        if { ![info exist ::t_putz] } {
            set ::t_putz 1
            package require Tk
            text .ttttt
            pack .ttttt -side left -fill both -expand 1
            .ttttt tag configure normal             -foreground black
            .ttttt tag configure red                -foreground red -font {courier 10}
        catch {
            .ttttt insert end $arg\n $color
            .ttttt see end
    for {set n 0} {$n < 6 } {incr n} {
        putz "Testing $n"   normal
        putz "Testing $n"   red
proc wait { ms } {              
    after $ms set ::__sleep__tmp 1
    vwait ::__sleep__tmp
for {set n 0} {$n < 10 } {incr n} {
	thread::create $script
	wait 400

after 20000 exit
wait 2500
puts donex4 

On windows this never fails.

Running this over and over using a bash script produced lines like this:

Xft: locking error too many file unlocks
Xft: locking error too many file unlocks line 19: 53611 Segmentation fault /usr/bin/tclsh crash.tcl
Xlib: charsets ISO8859-3:GR and ISO8859-3:GR have the same CT sequence
Xlib: charsets ISO8859-13:GR and ISO8859-13:GR have the same CT sequence

[xcb] Unknown request in queue while appending request
[xcb] Most likely this is a multi-threaded client and XInitThreads has
not been called
[xcb] Aborting, sorry about that.

tclsh: ../../src/xcb_io.c:151: append_pending_request: Assertion
`!xcb_xlib_unknown_req_pending' failed. line 24: 53671 Aborted /usr/bin/tclsh crash.tcl line 26: 53695 Segmentation fault /usr/bin/tclsh crash.tcl line 29: 53734 Segmentation fault /usr/bin/tclsh crash.tcl
User Comments: jan.nijtmans added on 2021-10-14 10:09:44:

> Now, the usual fine question is, does it need TIP'ery ...

How about TIP #364? If we support building with --enable-threads, it should work, shouldn't it?

@chw, Thanks for you thorough analysis! diff applied now.

chw added on 2021-10-13 23:03:20:
After playing with a modified copy of libXft which supports rendering
truetype color fonts (Noto Color Emoji for example) and adapting it as
a statically linked component in vanillawish (see the check-ins following

) my final conclusion on libXft: no thread support at all (and the success
story is, that vanillawish renders color emojis. Progress!)

Thus it is crucial to serialize libXft calls as outlined in my initial patch
in order to make an X11/Xft based Tk working under all circumstances.

Now, the usual fine question is, does it need TIP'ery, or would some Tk
god use that diff, review it, and finally commit it?

anonymous added on 2021-09-19 09:48:54:
I'm the submitter here, and I only really work on windows. I do however, test my code on linux if I intend to share, and for that I have a ubunutu in a vm, but I don't know enough linux to do anything more than just run the program. 

What I can add is that I can get it to fail more often if I remove the wait 400 between thread creates, and I can even reduce the script then to just a package require Tk (plus the thread::wait). 

I've run it in so many different ways I am forgetting just which ones I've done. Sometimes It will only crash 1 in a 1000 tries. It seems very much a timing problem, since with only 1 thread I don't think it crashes at all, but I can't be absolutely certain. And the crashes are all different, except that many do have something to do with malloc. I ran it with valgrind the memory leak detector and it reported errors, but I can't really say what the output was saying.

chw added on 2021-09-19 09:39:33:
Here's the simplified test case from the OP from


package require Thread

set script {
    package require Tk
proc wait { ms } {
    after $ms set ::__sleep__tmp 1
    vwait ::__sleep__tmp
for {set n 0} {$n < 5 } {incr n} {
    thread::create $script

after 20000 exit
wait 2500
puts donex4a

chw added on 2021-09-19 09:33:26:
Meanwhile, I believe, that Xft is not thread safe w.r.t. its management
of freetype font files (did some source code reading). Please try the
attached patch for core-8-6-branch tkUnixRFont.c which does some brute
force locking using a single mutex. Costs performance but hopefully
fixes these crashes.

chw added on 2021-09-19 06:46:00:
What about running the same test with a Tk build using --disable-xft to
narrow the problem down? To see if Xft is the culprit.