Browse Source

Fix threading issue with GUI. #1443 #1444

Alessandro Ranellucci 11 years ago
parent
commit
ed529b62f3
5 changed files with 62 additions and 9 deletions
  1. 1 0
      lib/Slic3r.pm
  2. 14 6
      lib/Slic3r/GUI/Plater.pm
  3. 7 2
      lib/Slic3r/GUI/SkeinPanel.pm
  4. 1 1
      lib/Slic3r/Print/Object.pm
  5. 39 0
      t/threads.t

+ 1 - 0
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 {

+ 14 - 6
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);

+ 7 - 2
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,
     );
 }
 

+ 1 - 1
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

+ 39 - 0
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__