From ed529b62f31117e7c728267f460d806f6766335b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 19 Sep 2013 16:00:47 +0200 Subject: [PATCH] Fix threading issue with GUI. #1443 #1444 --- lib/Slic3r.pm | 1 + lib/Slic3r/GUI/Plater.pm | 20 ++++++++++++------ lib/Slic3r/GUI/SkeinPanel.pm | 9 +++++++-- lib/Slic3r/Print/Object.pm | 2 +- t/threads.t | 39 ++++++++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 t/threads.t diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 921530a52..bb04f3f2f 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -136,6 +136,7 @@ sub thread_cleanup { *Slic3r::Surface::DESTROY = sub {}; *Slic3r::Surface::Collection::DESTROY = sub {}; *Slic3r::TriangleMesh::DESTROY = sub {}; + return undef; # this prevents a "Scalars leaked" warning } sub encode_path { diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 56d90fa91..286ad7226 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -612,13 +612,14 @@ sub export_gcode { return; } - # get config before spawning the thread because ->config needs GetParent and it's not available there - my $print = $self->skeinpanel->init_print; + # get config before spawning the thread because it needs GetParent and it's not available there + my $config = $self->skeinpanel->config; + my $extra_variables = $self->skeinpanel->extra_variables; # select output file $self->{output_file} = $main::opt{output}; { - $self->{output_file} = $print->expanded_output_filepath($self->{output_file}, $self->{objects}[0]->input_file); + $self->{output_file} = $self->skeinpanel->init_print->expanded_output_filepath($self->{output_file}, $self->{objects}[0]->input_file); my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', Slic3r::GUI->output_path(dirname($self->{output_file})), basename($self->{output_file}), &Slic3r::GUI::SkeinPanel::FILE_WILDCARDS->{gcode}, wxFD_SAVE); if ($dlg->ShowModal != wxID_OK) { @@ -643,7 +644,8 @@ sub export_gcode { @_ = (); $self->{export_thread} = threads->create(sub { $self->export_gcode2( - $print, + $config, + $extra_variables, $self->{output_file}, progressbar => sub { Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([@_]))) }, message_dialog => sub { Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $MESSAGE_DIALOG_EVENT, shared_clone([@_]))) }, @@ -665,7 +667,8 @@ sub export_gcode { }); } else { $self->export_gcode2( - $print, + $config, + $extra_variables, $self->{output_file}, progressbar => sub { my ($percent, $message) = @_; @@ -681,12 +684,17 @@ sub export_gcode { sub export_gcode2 { my $self = shift; - my ($print, $output_file, %params) = @_; + my ($config, $extra_variables, $output_file, %params) = @_; local $SIG{'KILL'} = sub { Slic3r::debugf "Exporting cancelled; exiting thread...\n"; threads->exit(); } if $Slic3r::have_threads; + my $print = Slic3r::Print->new( + config => $config, + extra_variables => $extra_variables, + ); + eval { $print->config->validate; $print->add_model($self->make_model); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 7f4236b0b..51066cc3b 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -228,7 +228,7 @@ sub repair_stl { Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair"); } -sub init_print { +sub extra_variables { my $self = shift; my %extra_variables = (); @@ -236,10 +236,15 @@ sub init_print { $extra_variables{"${_}_preset"} = $self->{options_tabs}{$_}->current_preset->{name} for qw(print filament printer); } + return { %extra_variables }; +} + +sub init_print { + my $self = shift; return Slic3r::Print->new( config => $self->config, - extra_variables => { %extra_variables }, + extra_variables => $self->extra_variables, ); } diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 77838ab8f..a10a5e81a 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -139,7 +139,7 @@ sub slice { # free memory undef $mesh; - undef $self->meshes->[$region_id]; + undef $self->meshes->[$region_id];return; } # free memory diff --git a/t/threads.t b/t/threads.t new file mode 100644 index 000000000..420d58f36 --- /dev/null +++ b/t/threads.t @@ -0,0 +1,39 @@ +use Test::More; +use strict; +use warnings; + +BEGIN { + use FindBin; + use lib "$FindBin::Bin/../lib"; +} + +use List::Util qw(first); +use Slic3r; +use Slic3r::Test; + +if (!$Slic3r::have_threads) { + plan skip_all => "this perl is not compiled with threads"; +} +plan tests => 2; + +{ + my $print = Slic3r::Test::init_print('20mm_cube'); + { + my $thread = threads->create(sub { Slic3r::thread_cleanup(); return 1; }); + ok $thread->join, "print survives thread spawning"; + } +} + +{ + my $thread = threads->create(sub { + # $print can't be inizialized outside the thread because Object->slice will + # modify it by removing meshes and popping layers + my $print = Slic3r::Test::init_print('20mm_cube'); + Slic3r::Test::gcode($print); + Slic3r::thread_cleanup(); + return 1; + }); + ok $thread->join, "process print in a separate thread"; +} + +__END__