Tk Source Code

View Ticket
Login
Ticket UUID: f4213443734676892385d998eae648aa9a4a5c70
Title: Crash following destroy command on a widget menu
Type: Bug Version: 8.6.14
Submitter: anonymous Created on: 2024-07-19 08:50:02
Subsystem: 13. Win Menus Assigned To: nobody
Priority: 5 Medium Severity: Severe
Status: Closed Last Modified: 2024-07-21 16:26:47
Resolution: Duplicate Closed By: fvogel
    Closed on: 2024-07-21 16:26:47
Description:
(can be a duplicate of [2d3a81c0] but not sure)

platform : MS WIndows 7 And 10 (64 bit)
distribution : Magicsplat Tcl/Tk 1.14.0 (Tcl 8.6.14)

The following script displays a treectrl with 2 columns "Actif" and "Line" filled with 20 lines.

The crash happen :
1) right click on header of column "Line" -> list of menu items appears
2) select menu item "10"
3) redo 1) and select menu item "(All)" -> crash



package require Tk
package require treectrl

wm withdraw .

#-------------------------------------------------------------------------------
proc RefreshTreectrl {} {
    # Proc called : - at the launch of script
    #               - by binding on menu item "(All)" or "10" (after right-click on header of colonne "Line")
    
    # Purpose : create some lines in a treectrl whose number vary with variable "::maxLine"
    
    # delete pre-existing lines if not empty :
    if {[.test.tree item children root] ne ""} {
        
        .test.tree item delete [.test.tree item firstchild root] [.test.tree item lastchild root]
    }
    
    # Create some lines with 2 columns
        
        for {set i 1} {$i <= $::maxLine} {incr i} {
            
            # create line
            set item [.test.tree item create -parent root]
            
            # fill first column "Actif" (display a checkbutton)
                
                destroy .test.tree.chb${item}
                
                set ::vect_Actif($item) 1
                set chBx [checkbutton .test.tree.chb${item} -variable ::vect_Actif($item)]
                
                .test.tree item style set $item 0 s1
                .test.tree item text $item 0 1
                .test.tree item element configure $item 0 eWindow -window $chBx -clip 1
                
            
            # fill second column "Line"
                
                .test.tree item style set $item 1 s2
                .test.tree item text $item 1 $i
        }
}
#-------------------------------------------------------------------------------

toplevel .test
    
wm protocol .test WM_DELETE_WINDOW {exit}

pack [treectrl .test.tree] -fill both -expand 1
    
    # Colmuns in treectrl :
        
        .test.tree column create -text Actif
        .test.tree column create -text Line
    
    # Styles in treectrl :
        
        .test.tree element create el1 text -lines 1
        .test.tree element create eWindow window -clip yes -destroy yes
        .test.tree element create el2 rect -open nw -outline gray -outlinewidth 1 -fill [list grey87 selected]
        
        # column Actif's style 
        .test.tree style create s1
        .test.tree style elements s1 [list el2 eWindow]
        .test.tree style layout s1 el2     -detach yes -iexpand yx
        .test.tree style layout s1 eWindow -iexpand nsew -ipadx 1 -ipady 1
        
        # column Line's style 
        .test.tree style create s2
        .test.tree style elements s2 [list el2 el1]
        .test.tree style layout s2 el2 -detach yes -iexpand yx
        .test.tree style layout s2 el1 -iexpand nsew -ipadx 4 -ipady 4
    
    bind .test.tree <3> {
        # Right-click on header of the column "Line" : create a menu widget ".menuDeroulant"
        # and display 2 menu items : "(All)" and "10"
        
        # click on one menu item to change the value of the variable "::maxLine"
        # and replace current treectrl taking into account the new valeur of ::maxLine
        
        if {   [lindex [%W identify %x %y] 0] eq "header"
            && [lindex [%W identify %x %y] 1] == 1} {
            
            menu .menuDeroulant
            
            # menu item "(All)" (set ::maxLine to 20)
                
                set ::chbVar(All) 0
                
                .menuDeroulant add checkbutton -label "(All)" -variable ::chbVar(All) \
                                               -command  {
                    
                    destroy .menuDeroulant
                    
                    set ::maxLine 20
                    
                    RefreshTreectrl
                }
            
            # menu item "10" (set ::maxLine to 10)
                
                if {$::maxLine == 10} {
                    
                    set ::chbVar(10) 1
                    
                } else {
                    
                    set ::chbVar(10) 0
                }
                
                .menuDeroulant add checkbutton -label 10 -variable ::chbVar(10) \
                                               -command {
                    
                    destroy .menuDeroulant
                    
                    set ::maxLine 10
                    
                    RefreshTreectrl
                }
            
            # Display all items of the menu in widget ".menuDeroulant"
                
                set x [expr {[winfo rootx .test.tree] + [lindex [.test.tree column bbox 1] 0] + 1}]
                set y [expr {[winfo rooty .test.tree] + [lindex [.test.tree column bbox 1] 3] + 1}]
                
                tk_popup .menuDeroulant $x $y
        }
    }

    # Display 20 lines in the widget treectrl
        
        set ::maxLine 20
        
        RefreshTreectrl
User Comments: fvogel added on 2024-07-21 16:26:47:

I can confirm that:

a. The script in attachment crashes for me on Windows when applying the provided recipe, which is:
"
The crash happen :
1) right click on header of column "Line" -> list of menu items appears
2) select menu item "10"
3) redo 1) and select menu item "(All)" -> crash
"
b. This does not happen in branch ticket-2d3a81c0-menubutton-destroy-segfault that fixes [2d3a81c0ec]

So the present ticket is a duplicate of [2d3a81c0ec], I'm closing it as such.


fvogel added on 2024-07-21 16:25:16:
I can confirm that:

  a.  The script in attachment crashes for me on Windows when applying the provided recipe, which is:

The crash happen :
1) right click on header of column "Line" -> list of menu items appears
2) select menu item "10"
3) redo 1) and select menu item "(All)" -> crash

  b.  This does not happen in branch [https://core.tcl-lang.org/tk/timeline?r=ticket-2d3a81c0-menubutton-destroy-segfault|ticket-2d3a81c0-menubutton-destroy-segfault] that fixes [2d3a81c0ec]

So the present ticket is a duplicate of [2d3a81c0ec], I'm closing it as such.

marc_culler (claiming to be Marc Culler) added on 2024-07-19 13:53:38:
Thanks, Harald.  But I don't think I am responsible for that.

oehhar added on 2024-07-19 13:40:12:
Yes, Marc. As you can see in the bugfix, the solution from MacOS was copied to Windows.

It is probably your great work !

Harald

anonymous added on 2024-07-19 13:31:27:
the 3rd time is the right one (sorry for the inconvenience) :



package require Tk

wm withdraw .

#-------------------------------------------------------------------------------
proc Refresh {} {
    # Proc called : - at the launch of script
    #               - by binding on menu item "(All)" or "10" (after right-click on the label "Line")
    
    # Purpose : create some checkbuttons and labels whose number vary with variable "::maxLine_New"
    
    # delete pre-existing checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_Old} {incr i} {
        
        destroy .test.chb$i .test.line$i
    }
    
    # Create some checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_New} {incr i} {
        
        set ::vect_Actif($i) 1
        
        grid [checkbutton .test.chb$i -variable ::vect_Actif($i)] -row $i -column 0
        
        grid [ttk::label .test.line$i -text $i] -row $i -column 1
    }
}
#-------------------------------------------------------------------------------

toplevel .test
    
wm protocol .test WM_DELETE_WINDOW {exit}

grid [ttk::label .test.headerActif -text Actif] -row 0 -column 0
grid [ttk::label .test.headerLine -text Line]  -row 0 -column 1
    
    bind .test.headerLine <3> {
        # Right-click on the label "Line" : create a menu widget ".menuDeroulant"
        # and display 2 menu items : "(All)" and "10"
        
        # click on one menu item to change the value of the variables "::maxLine_Old" and "::maxLine_New"
        # and call proc Refresh
        
        destroy .menuDeroulant
        menu .menuDeroulant
        
        # menu item "(All)" (set ::maxLine_New to 20)
            
            set ::chbVar(All) 0
            
            .menuDeroulant add checkbutton -label "(All)" -variable ::chbVar(All) \
                                           -command  {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 20
                
                Refresh
            }
        
        # menu item "10" (set ::maxLine_New to 10)
            
            if {$::maxLine_New == 10} {
                
                set ::chbVar(10) 1
                
            } else {
                
                set ::chbVar(10) 0
            }
            
            .menuDeroulant add checkbutton -label 10 -variable ::chbVar(10) \
                                           -command {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 10
                
                Refresh
            }
        
        # Display all items of the menu in widget ".menuDeroulant"
            
            set x [expr {[winfo rootx .test] + %x + 1}]
            set y [expr {[winfo rooty .test] + %y + 1}]
            
            tk_popup .menuDeroulant $x $y
    }
    
    # Display 20 pairs of checkbuttons et labels
        
        set ::maxLine_Old 0     ;# number of pre-existsing pairs
        set ::maxLine_New 20    ;# number of pairs to create
        
        Refresh

marc_culler (claiming to be Marc Culler) added on 2024-07-19 13:31:10:
I tested this on macOS 14 with Tcl and Tk 9.0b3.

There is an error in the (second) script.  The proc RefreshTreeview
is not defined. I replaced RefreshTreeview by Refresh in both places.
Then the script ran fine.  There was no crash.

So this bug appears to be specific to Windows.

I will upload a corrected version of the script which also changes the
header on the second column to "Line".

anonymous added on 2024-07-19 13:29:02:
I'm sorry, there are mistakes in the script.
The proc called should have been "Refresh" and the second label "Actif" should be renamed "Line"

Below is the script corrected :


package require Tk

wm withdraw .

#-------------------------------------------------------------------------------
proc Refresh {} {
    # Proc called : - at the launch of script
    #               - by binding on menu item "(All)" or "10" (after right-click on the label "Line")
    
    # Purpose : create some checkbuttons and labels whose number vary with variable "::maxLine_New"
    
    # delete pre-existing checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_Old} {incr i} {
        
        destroy .test.chb$i .test.line$i
    }
    
    # Create some checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_New} {incr i} {
        
        set ::vect_Actif($i) 1
        
        grid [checkbutton .test.chb$i -variable ::vect_Actif($i)] -row $i -column 0
        
        grid [ttk::label .test.line$i -text $i] -row $i -column 1
    }
}
#-------------------------------------------------------------------------------

toplevel .test
    
wm protocol .test WM_DELETE_WINDOW {exit}

grid [ttk::label .test.headerActif -text Actif] -row 0 -column 0
grid [ttk::label .test.headerLine -text Actif]  -row 0 -column 1
    
    bind .test.headerLine <3> {
        # Right-click on the label "Line" : create a menu widget ".menuDeroulant"
        # and display 2 menu items : "(All)" and "10"
        
        # click on one menu item to change the value of the variables "::maxLine_Old" and "::maxLine_New"
        # and call proc Refresh
        
        destroy .menuDeroulant
        menu .menuDeroulant
        
        # menu item "(All)" (set ::maxLine_New to 20)
            
            set ::chbVar(All) 0
            
            .menuDeroulant add checkbutton -label "(All)" -variable ::chbVar(All) \
                                           -command  {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 20
                
                Refresh
            }
        
        # menu item "10" (set ::maxLine_New to 10)
            
            if {$::maxLine_New == 10} {
                
                set ::chbVar(10) 1
                
            } else {
                
                set ::chbVar(10) 0
            }
            
            .menuDeroulant add checkbutton -label 10 -variable ::chbVar(10) \
                                           -command {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 10
                
                Refresh
            }
        
        # Display all items of the menu in widget ".menuDeroulant"
            
            set x [expr {[winfo rootx .test] + %x + 1}]
            set y [expr {[winfo rooty .test] + %y + 1}]
            
            tk_popup .menuDeroulant $x $y
    }
    
    # Display 20 pairs of checkbuttons et labels
        
        set ::maxLine_Old 0     ;# number of pre-existsing pairs
        set ::maxLine_New 20    ;# number of pairs to create
        
        Refresh


Thanks
Jean-Baptiste

oehhar added on 2024-07-19 13:13:59:
I can confirm, that:

   *   with my wish 8.6.14, your test crashes
   *   The version in branch [ticket-2d3a81c0-menubutton-destroy-segfault] does not crash, but shows an error box "Invalid command name "RefreshTreeview""

Nobody was so far able to reproduce the error script in ticket [2d3a81c0].
Perhaps, this one may bereproductible.

We are looking for a test case for this.
Eventually, your one may be suited for this.

A note on the instructions: right click on the 2nd label with the text "Actif".
I just copied the script into the wish console window.

Thank you !
Harald

anonymous added on 2024-07-19 12:56:44:
Below is a new script without treectrl package.
Here, for the crash to happen :
1) right click on the label "Line" -> list of menu items appears
2) select any menu item ("10" or "(All)") -> crash



package require Tk

wm withdraw .

#-------------------------------------------------------------------------------
proc Refresh {} {
    # Proc called : - at the launch of script
    #               - by binding on menu item "(All)" or "10" (after right-click on the label "Line")
    
    # Purpose : create some checkbuttons and labels whose number vary with variable "::maxLine_New"
    
    # delete pre-existing checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_Old} {incr i} {
        
        destroy .test.chb$i .test.line$i
    }
    
    # Create some checkbuttons and labels :
    for {set i 1} {$i <= $::maxLine_New} {incr i} {
        
        set ::vect_Actif($i) 1
        
        grid [checkbutton .test.chb$i -variable ::vect_Actif($i)] -row $i -column 0
        
        grid [ttk::label .test.line$i -text $i] -row $i -column 1
    }
}
#-------------------------------------------------------------------------------

toplevel .test
    
wm protocol .test WM_DELETE_WINDOW {exit}

grid [ttk::label .test.headerActif -text Actif] -row 0 -column 0
grid [ttk::label .test.headerLine -text Actif]  -row 0 -column 1
    
    bind .test.headerLine <3> {
        # Right-click on the label "Line" : create a menu widget ".menuDeroulant"
        # and display 2 menu items : "(All)" and "10"
        
        # click on one menu item to change the value of the variables "::maxLine_Old" and "::maxLine_New"
        # and call proc Refresh
        
        destroy .menuDeroulant
        menu .menuDeroulant
        
        # menu item "(All)" (set ::maxLine_New to 20)
            
            set ::chbVar(All) 0
            
            .menuDeroulant add checkbutton -label "(All)" -variable ::chbVar(All) \
                                           -command  {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 20
                
                RefreshTreeview
            }
        
        # menu item "10" (set ::maxLine_New to 10)
            
            if {$::maxLine_New == 10} {
                
                set ::chbVar(10) 1
                
            } else {
                
                set ::chbVar(10) 0
            }
            
            .menuDeroulant add checkbutton -label 10 -variable ::chbVar(10) \
                                           -command {
                
                destroy .menuDeroulant
                
                set ::maxLine_Old $::maxLine_New
                set ::maxLine_New 10
                
                RefreshTreeview
            }
        
        # Display all items of the menu in widget ".menuDeroulant"
            
            set x [expr {[winfo rootx .test] + %x + 1}]
            set y [expr {[winfo rooty .test] + %y + 1}]
            
            tk_popup .menuDeroulant $x $y
    }
    
    # Display 20 pairs of checkbuttons et labels
        
        set ::maxLine_Old 0     ;# number of pre-existsing pairs
        set ::maxLine_New 20    ;# number of pairs to create
        
        Refresh

oehhar added on 2024-07-19 11:35:17:

I tried to compile tktreectrl from: https://github.com/apnadkarni/tktreectrl

but it does not compile.

So, I am sorry, I can not verify the issue.

Take care, Harald


anonymous added on 2024-07-19 11:35:13:
Hello harald

I have runned the script in ticket 2d3a81c0 and it doesn't crash on my system (Win 7)

Thanks

Jean-Baptiste

oehhar added on 2024-07-19 10:12:46:

The problem of [2d3a81c0] is, that nobody can reproduce it. Can you reproduce the crash in the test in this ticket?

I will try to reproduce your issue next week.

Thanks, it is great to report bugs ! Harald


oehhar added on 2024-07-19 10:10:53:

It would be great to check, if this bugfix branch will cure the issue: [ticket-2d3a81c0-menubutton-destroy-segfault].

I have no time to check now, but the description is the same.

Take care, Harald


Attachments: