in reply to Getting segfaults when destroying and recreating Tk box

Well your last script version dosn't segfault for me on linux, but I must tell you that you are thinking about Tk-programming the wrong way, and it is biting you. Why? You are destroying the mainloop, then trying to recreate it before it is destroyed. This is asking for weird problems with system timing, etc, and produces unpredictable results.

NEVER write scripts that try to create-destroy-create a MainWindow. The MainWindow in Tk IS the eventloop. The eventloop MUST continue to run for proper operation, and trying to destroy it, with some code saying "restart yourself at death" is not going to be reliable.

The way you approach your type of script, is to make one mainwindow,and then some "toplevel" windows to present information. You can destroy a toplevel window, without it affecting the mainwindow's eventloop; but repeated create/destroy cycles of a toplevel window, may cause a memory gain, so you should always design scripts to reuse windows...... don't destroy them, just withdraw them, then repack them with different widgets.

Here is a way to use your code .

#!/usr/bin/perl -w use Tk; use strict; my $MW; my $Array_Index=""; my @Widget_List; my $my_ref; my @file_references ; my $i; $MW = MainWindow->new; push @Widget_List, $MW->title("test box 1"); push @Widget_List, $MW->Label(-text=>"Choose one option", -font=>"courierfont") -> pack; @file_references = ("Ref1", "Ref2", "Ref3", "Ref4"); $i=1; foreach $my_ref (@file_references) { push @Widget_List, $MW->Button(-text => "$my_ref", -command => [ \&do_button, "$my_ref,$i"]) -> pack; $i++; } MainLoop(); sub do_button { my $params; my $widget; $params = shift; (my $ref, $Array_Index) = split (/,/,$params); print "$params\n"; $MW->Label(-text=>"This line will not cause a segfault")->pack; foreach $widget (@Widget_List) { $widget->destroy(); } $MW->Button(-text => "Shutdown and close", -command => [ \&abort_routine]) -> pack; } sub abort_routine{ exit }

and a better way to do it

#!/usr/bin/perl use warnings; use strict; use Tk; my $MW = MainWindow->new; $MW->withdraw; $MW->Label(-text=>"This line will not cause a segfault")->pack; $MW->Button(-text => "Shutdown and close", -command => [ \&abort_routine]) -> pack; my $top = $MW->Toplevel(-bg=>'steelblue',-title=>"test box 1"); $top->Label(-text=>"Choose one option", -font=>"courierfont") -> pack; my @file_references = ("Ref1", "Ref2", "Ref3", "Ref4"); my $i=1; foreach my $my_ref (@file_references) { $top->Button(-text => "$my_ref", -command => [ \&do_button, "$my_ref,$i"]) -> pack; $i++; } MainLoop(); sub do_button { my $params; my $widget; $params = shift; (my $ref, my $Array_Index) = split (/,/,$params); print "$params\n"; $top->destroy(); $MW->deiconify; $MW->raise; } sub abort_routine{ exit }

I'm not really a human, but I play one on earth. Cogito ergo sum a bum

Replies are listed 'Best First'.
Re^2: Getting segfaults when destroying and recreating Tk box
by skt (Initiate) on Sep 06, 2007 at 01:00 UTC
    Arghhh. Thanks for the tip. It all makes sense now and indeed, the segmentation faults disappear when following your suggested strategy of avoiding destroys.

    I note that if you ever destroy a TopLevel window, you eventually provoke another segmentation fault. However if you withdraw the TopLevel windows instead of destroying them, you can go on seemingly indefinitely by withdrawing the old TopLevel window and then defining a subsequent TopLevel window.

    Then to exit the MainLoop gracefully, you destroy the original (hidden and withdrawn) MainWindow.

    Thanks,
    Stefan

      I note that if you ever destroy a TopLevel window, you eventually provoke another segmentation fault.

      That dosn't sound right. You may have a Tk version that needs patching, or you are doing something weird like trying to access a widget packed in the toplevel, after you destroy the toplevel.

      If you want to be happy with Tk, stop using destroy to eliminate windows. To exit gracefully, use plain old "exit" or "Tk::exit", they clean up. If you use $mw->destroy, you may be leaving the calling shell alive. Of course, that may be useful in certain circumstances.

      #!/usr/bin/perl -w use Tk; my $mw = MainWindow->new(-title=>"#1"); $mw->Button(-text=>"Destroy Me", -command=> sub { $mw->destroy })->pack; $mw->Button(-text=>"Exit Me", -command=> sub { Tk::exit })->pack; MainLoop; print "ha ha still going\n"; <>;

      I'm not really a human, but I play one on earth. Cogito ergo sum a bum