Tk Source Code

View Ticket
Login
Ticket UUID: c60758248980500471516784a10a530517ce6660
Title: Tk crashes X server drawing multi-segment dashed lines
Type: Bug Version: 8.5.9, 8.6.1, 8.6.2
Submitter: ian_gay Created on: 2014-10-25 18:41:41
Subsystem: 05. Canvas Items Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Severe
Status: Closed Last Modified: 2015-03-19 14:58:42
Resolution: Invalid Closed By: dkf
    Closed on: 2015-03-19 14:58:42
Description:
 Tk crashes when drawing multi-segment dashed lines that extend
 outside the visible area of the canvas. This crash is observed
 running Linux (opensuse 13.1) on intel i5-2500k with on-chip
 graphics. The crash occurs with both KDE and icewm. The actual
 crash is termination of the X server with a segfault.
 
 The crash does not occur if the default intel video driver is
 replaced by the (slow) fbdev driver. This suggests a bug in the
 driver, but
 a) No other program has ever caused a similar crash on this computer
 b) The crash can be prevented by seemingly trivial changes in the Tk code.
 
 The crash can be generated by the script below. It does not occur
 every time a line is drawn, hence the loop. After a crash, the file
 crash_count indicates how many times the loop ran successfully.
 Typically less than 100 loop iterations are required for a crash.
 
 If _any_ of the following modifications are made to this script, no
 crashes occur:
 a) Change canvas dimensions to 600 x 600
 b) Change -dash value to {}
 c) Change -width value to 2
 d) Lines with < 20 segments don't crash (not exhaustively tested)
 
 ------------------------------- Cut here -----------------------------
 #! /usr/bin/env tclsh
 
 # WARNING THIS WILL DESTROY ANY FILE NAMED crash_count
 
 package require Tk
 
 set pts {
    229 229 223 234 217 240 211 246 205 252 200 258 195 264 189 270 184
    276 179 282 174 288 169 294 164 300 160 306 155 312 151 318 146 324
    142 330 138 336 134 341 130 347 126 353 123 358 119 364 116 370 113
    375 109 381 106 386 104 391 101 397 98 402 96 407 93 412 91 417 89
    422 87 427 86 432 84 436 82 441 81 445 80 450 79 454 78 458 77 462
    77 466 76 470 76 474 76 478 76 481 76 485 77 488 77 491 78 494 79
    497 80 500 81 502 82 505 84 507 86 509 88 512
 }
 
 proc main {} {
    global pts
    puts "tcl version: [info patch]"
    flush stdout
    
    canvas .c -width 400 -height 400 -bg white
    pack .c -fill both -expand 1
    
    file delete crash_count
    
    set N 5000
    for {set i 0} {$i < $N} {incr i} {
       
      .c create line $pts -fill blue -dash {3 3} -width 1
 
       update idletasks
       set f [open crash_count w]
       puts $f $i
       close $f
       .c delete all
    }
    puts "done $N cycles"
 }
 
 main
User Comments: dkf added on 2015-03-19 14:58:42:

Since it's not our bug and is fixed upstream, I'll close this. (Should've been closed months ago…)


ian_gay added on 2014-11-12 21:29:15:
I filed a bug with x.org, and they produced a patch to the intel video driver, which seems to have cured the problem. So, definitely not a Tk bug.

Ian

ian_gay added on 2014-11-07 19:07:37:
You are right. I managed to produce the same crash making xlib calls from C. (Though not as easily as with Tk!). So it must be bug in xserver/video driver, or in xlib. Are you confident of the good behaviour of xlib? I have got the x.org server, and the crash occurs for versions 1.14.3, 1.16.0 and 1.16.1. Do you happen to know anything about these?

dkf added on 2014-11-07 09:21:29:

Have you reported this to the relevant Xserver maintainers? Having a client request crash their server would seem to be a serious bug in their code. (I suspect we could distill the code down to a fairly short C program that causes the crash.) That Tk triggers the problem is unfortunate, but we aren't deliberately setting out to cause problems so the problem is at their end.

Tempted to call "CLOSED INVALID" on this.


ian_gay added on 2014-10-31 18:57:27:
It doesn't crash if I specify -joinstyle miter. It does crash for round (the default) and for bevel.

ian_gay added on 2014-10-30 22:21:16:
 -dash {4} never crashes
 -dash {3} crashes on 8.5.0, 8.5.7 and 8.6.2 (Didn't try others)

So 8.5.8 update just revealed something that was already there.

dgp added on 2014-10-30 18:34:12:
Based on a quick read, it seems that in Tk older
than 8.5.8, Tk was simply failing to honor your
request for -dash {3 3} and boldly replace any
such request with effectively -dash {4 4}.

Older Tk won't let you demo the bug in your X server.

The old ticket suggests that a workaround might be
replacing all "-dash {n n}" with "-dash n".  That
might be a way to keep demoing the bug in your X server
with older Tk.  Or it might be a way to dodge the bug
in your X server with current Tk.

dgp added on 2014-10-30 18:26:14:
Believe it or not that helps!

Only change to canvas between releases Tk 8.5.7 and 8.5.8 was
the fix for bug 220935.

http://core.tcl.tk/tk/tktview?name=220935

which was checkin 7a24e314da

http://core.tcl.tk/tk/info/7a24e314da

Passing to jan.nijtmans in case he has any recollection
of this change, and how it might rub some broken X servers
the wrong way.

aku added on 2014-10-30 18:23:40:

Ok. Are you able to build Tcl/Tk yourself ?

If yes, please get the fossil SCM, check Tcl/Tk out on your system, and use the "fossil bisect" commands to narrow down on the checkout which started the trouble.


ian_gay added on 2014-10-30 18:05:08:
Looks like it's a regression in Tk, and not a problem with my system :)

I downloaded a bunch of tclkits starting from 8.5.0. There is no crash up to 8.5.7, it crashes with 8.5.8 and above.

ian_gay added on 2014-10-29 19:01:45:
Crash depends on the dash pattern. Previous tests were all done with -dash {3 3}. Today I tested all patterns of the form {n n} where n ranges from 2 to 20. It crashes for n = 3, 8, 9, 10, 15, 17 and 19. It does not crash for the others.

ian_gay added on 2014-10-28 22:42:39:
One can produce the same crash by first drawing the line solid (which never crashes) and then changing it to dashed with itemconfigure.

ian_gay added on 2014-10-27 18:55:52:
OK, by running gdb from the linux console (after setting DISPLAY) I can get a crash and see some messages afterwards.
If I don't use gdb, then after the crash, I see
---------------
XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
      after 126 requests (126 known processed) with 3 events remaining.
---------------
(The numbers vary from run to run)

If I run under gdb, I get a message like above, and an additional line
-----------
[Inferior 1 (process 1793) exited with code 01]
------------

If, at this point, I give the bt command to gdb, I simply get
------------
no stack
-------------

dgp added on 2014-10-27 17:51:36:
If you have the crash in gdb, then as a first step, 
use the "bt" command to produce the backtrace
leading up to the crash, and post it in a comment
here.

anonymous added on 2014-10-27 17:40:53:
It does crash in gdb, but I'm not expert in gdb, and unsure how to proceed effectively. Set a breakpoint on XDrawLines and then single step? Seems tedious! What do you suggest?

Further to number of points: if, instead of drawing all 60 segments in a single canvas create call, I use 2 consecutive calls of 30 ponits each it does not crash.

I'd really like to know if anyone can reproduce this - maybe I have a hardware problem. Anyone out there running Linux on an i5-2500K ?

dgp added on 2014-10-27 14:28:37:
Has the crash been captured in a debugger so
that we can know what library routine call by Tk
with what arguments are triggering the failure?

aku added on 2014-10-25 23:01:33:
Looking at the changes which can make the issue go away (d) looks to be the most promising for a solution at the C level. I.e. to have the canvas automatically split poly-lines with more than 20 segments into multiple lines each using less than 20 segments.

The only issue I can see with this would be the handling of a non-"round" join-style, i.e. "bevel" and "miter", at the split-points. I wonder if this do-able by using cap-style "butt" for the segment-end at the split, plus an overlapping segment which draws that join correct over the split-point.

I.e. instead of drawing the split as

*--- ... ---*
            *-----*--- ... ---*

use

*--- ... ---*-----|
            |-----*--- ... ---*

Of course, I am getting ahead here.

Have you continued to test (d) ?

Reading the description again you are also saying it happens only when going outside the visible area ?!

Then having Tk clipping the line to the area and removing the invisible pieces also helps ?!

That would then actually be the better solution, IMHO.