really kill background "find" in "new album" dialog when changing directory, reported...
authorGuillaume Cottenceau <gcottenc@gmail.com>
Tue, 16 Jun 2009 08:20:13 +0000 (10:20 +0200)
committerGuillaume Cottenceau <gcottenc@gmail.com>
Tue, 16 Jun 2009 08:20:13 +0000 (10:20 +0200)
bin/booh

index 174ec09..9fff6a8 100644 (file)
--- a/bin/booh
+++ b/bin/booh
@@ -3317,37 +3317,64 @@ def new_album
     tooltips.set_tip(madewithentry, utf8(_("Optional HTML markup to use on pages bottom for a small 'made with' label; %booh is replaced by the website of booh;\nfor example: made with <a href=%booh>booh</a>!")), nil)
 
     src_nb_calculated_for = ''
-    src_nb_thread = nil
+    src_nb_process = nil
     process_src_nb = proc {
         if src.text != src_nb_calculated_for
             src_nb_calculated_for = src.text
-            if src_nb_thread
-                Thread.kill(src_nb_thread)
-                src_nb_thread = nil
+            if src_nb_process
+                begin
+                    Process.kill(9, src_nb_process)
+                rescue Errno::ESRCH
+                    #- process doesn't exist anymore - race condition
+                end
             end
             if src_nb_calculated_for != '' && from_utf8_safe(src_nb_calculated_for) == ''
                 src_nb.set_markup(utf8(_("<span size='small'><i>invalid source directory</i></span>")))
             else
                 if File.directory?(from_utf8_safe(src_nb_calculated_for)) && src_nb_calculated_for != '/'
                     if File.readable?(from_utf8_safe(src_nb_calculated_for))
-                        src_nb_thread = Thread.new {
-                            gtk_thread_protect { src_nb.set_markup(utf8(_("<span size='small'><i>processing...</i></span>"))) }
-                            total = { 'image' => 0, 'video' => 0, nil => 0 }
-                            `find '#{from_utf8_safe(src_nb_calculated_for)}' -type d -follow`.each { |dir|
-                                if File.basename(dir) =~ /^\./
-                                    next
-                                else
-                                    begin
-                                        Dir.entries(dir.chomp).each { |file|
-                                            total[entry2type(file)] += 1
-                                        }
-                                    rescue Errno::EACCES, Errno::ENOENT
+                        rd, wr = IO.pipe
+                        if src_nb_process
+                            while src_nb_process
+                                msg 3, "sleeping for completion of previous process"
+                                sleep 0.05
+                            end
+                            gtk_thread_flush  #- flush to avoid race condition in src_nb markup update
+                        end
+                        src_nb.set_markup(utf8(_("<span size='small'><i>processing...</i></span>")))
+                        total = { 'image' => 0, 'video' => 0, nil => 0 }
+                        if src_nb_process = fork
+                            msg 3, "spawned #{src_nb_process} for #{src_nb_calculated_for}"
+                            #- parent
+                            wr.close
+                            Thread.new {
+                                rd.readlines.each { |dir|
+                                    if File.basename(dir) =~ /^\./
+                                        next
+                                    else
+                                        begin
+                                            Dir.entries(dir.chomp).each { |file|
+                                                total[entry2type(file)] += 1
+                                            }
+                                        rescue Errno::EACCES, Errno::ENOENT
+                                        end
                                     end
+                                }
+                                rd.close
+                                msg 3, "ripping #{src_nb_process}"
+                                dummy, exitstatus = Process.waitpid2(src_nb_process)
+                                if exitstatus == 0
+                                    gtk_thread_protect { src_nb.set_markup(utf8(_("<span size='small'><i>%s photos and %s videos</i></span>") % [ total['image'], total['video'] ])) }
                                 end
+                                src_nb_process = nil
                             }
-                            gtk_thread_protect { src_nb.set_markup(utf8(_("<span size='small'><i>%s photos and %s videos</i></span>") % [ total['image'], total['video'] ])) }
-                            src_nb_thread = nil
-                        }
+                            
+                        else
+                            #- child
+                            rd.close
+                            wr.write(`find '#{from_utf8_safe(src_nb_calculated_for)}' -type d -follow`)
+                            Process.exit!(0)  #- _exit
+                        end                       
                     else
                         src_nb.set_markup(utf8(_("<span size='small'><i>permission denied</i></span>")))
                     end
@@ -3524,8 +3551,16 @@ Are you sure you want to continue?")), { :okcancel => true })
         madewith = madewithentry.text.gsub('\'', '&#39;')  #- because the parameters to booh-backend are between apostrophes
         indexlink = indexlinkentry.text.gsub('\'', '&#39;')
     end
-    if src_nb_thread
-        Thread.kill(src_nb_thread)
+    if src_nb_process
+        begin
+            Process.kill(9, src_nb_process)
+            while src_nb_process
+                msg 3, "sleeping for completion of previous process"
+                sleep 0.05
+            end
+        rescue Errno::ESRCH
+            #- process doesn't exist
+        end
         gtk_thread_flush  #- needed because we're about to destroy widgets in dialog, for which they may be some pending gtk calls
     end
     dialog.destroy