sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit 21d2df8715f384cf2026c3990573853d9757c325
parent 52bf32738e89c5cffab04d42f058ae69791734b6
Author: wmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Date:   Tue, 12 Jun 2007 18:47:00 +0000

better resilience in the face of sources.yaml-destroying errors

git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@446 5c8cc53c-5e98-4d25-b20a-d8db53a31250

Diffstat:
M bin/sup | 12 +++++++++---
M lib/sup.rb | 10 +++++++---
M lib/sup/index.rb | 11 ++++++++---
M lib/sup/poll.rb | 10 ++++++++--
M lib/sup/suicide.rb | 10 ++++++++--
5 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/bin/sup b/bin/sup
@@ -171,8 +171,8 @@ begin
   imode.load_threads :num => ibuf.content_height, :when_done => lambda { reporting_thread { sleep 1; PollManager.poll } }
 
   unless $opts[:no_threads]
-    PollManager.start_thread
-    SuicideManager.start_thread
+    PollManager.start
+    SuicideManager.start
     Index.start_lock_update_thread
   end
 
@@ -253,6 +253,12 @@ begin
 rescue Exception => e
   $exception ||= e
 ensure
+  unless $opts[:no_threads]
+    PollManager.stop
+    SuicideManager.stop
+    Index.stop_lock_update_thread
+  end
+
   Redwood::finish
   stop_cursing
 
@@ -284,7 +290,7 @@ Sincerely,
 William
 ----------------------------------------------------------------
 
-The problem was: #{$exception.message} (error type #{$exception.class.name})
+The problem was: '#{$exception.message}' (error type #{$exception.class.name})
 A backtrace follows:
 EOS
   raise $exception
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -70,9 +70,12 @@ module Redwood
   module_function :reporting_thread
 
 ## one-stop shop for yamliciousness
-  def save_yaml_obj object, fn, compress=false
-    if compress
-      Zlib::GzipWriter.open(fn) { |f| f.puts object.to_yaml }
+  def save_yaml_obj object, fn, safe=false
+    if safe
+      safe_fn = "safe_#{fn}"
+      mode = File.stat(fn) if File.exists? fn
+      File.open(safe_fn, "w", mode) { |f| f.puts object.to_yaml }
+      FileUtils.mv safe_fn, fn
     else
       File.open(fn, "w") { |f| f.puts object.to_yaml }
     end
@@ -101,6 +104,7 @@ module Redwood
   end
 
   def finish
+    Redwood::PollManager.stop
     Redwood::LabelManager.save if Redwood::LabelManager.instantiated?
     Redwood::ContactManager.save if Redwood::ContactManager.instantiated?
     Redwood::PersonManager.save if Redwood::PersonManager.instantiated?
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -46,7 +46,7 @@ class Index
   end
 
   def start_lock_update_thread
-    Redwood::reporting_thread do
+    @lock_update_thread = Redwood::reporting_thread do
       while true
         sleep 30
         @lock.touch_yourself
@@ -54,6 +54,11 @@ class Index
     end
   end
 
+  def stop_lock_update_thread
+    @lock_update_thread.kill if @lock_update_thread
+    @lock_update_thread = nil
+  end
+
   def fancy_lock_error_message_for e
     secs = Time.now - e.mtime
     mins = secs.to_i / 60
@@ -373,9 +378,9 @@ protected
       bakfn = fn + ".bak"
       if File.exists? fn
         File.chmod 0600, fn
-        FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(bakfn) > File.size(fn)
+        FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(fn) == 0
       end
-      Redwood::save_yaml_obj @sources.values.sort_by { |s| s.id.to_i }, fn
+      Redwood::save_yaml_obj @sources.values.sort_by { |s| s.id.to_i }, fn, true
       File.chmod 0600, fn
     end
     @sources_dirty = false
diff --git a/lib/sup/poll.rb b/lib/sup/poll.rb
@@ -9,6 +9,7 @@ class PollManager
 
   def initialize
     @mutex = Mutex.new
+    @thread = nil
     @last_poll = nil
     
     self.class.i_am_the_instance self
@@ -29,8 +30,8 @@ class PollManager
     [num, numi]
   end
 
-  def start_thread
-    Redwood::reporting_thread do
+  def start
+    @thread = Redwood::reporting_thread do
       while true
         sleep DELAY / 2
         poll if @last_poll.nil? || (Time.now - @last_poll) >= DELAY
@@ -38,6 +39,11 @@ class PollManager
     end
   end
 
+  def stop
+    @thread.kill if @thread
+    @thread = nil
+  end
+
   def do_poll
     total_num = total_numi = 0
     @mutex.synchronize do
diff --git a/lib/sup/suicide.rb b/lib/sup/suicide.rb
@@ -8,14 +8,15 @@ class SuicideManager
   def initialize fn
     @fn = fn
     @die = false
+    @thread = nil
     self.class.i_am_the_instance self
     FileUtils.rm_f @fn
   end
 
   bool_reader :die
 
-  def start_thread
-    Redwood::reporting_thread do
+  def start
+    @thread = Redwood::reporting_thread do
       while true
         sleep DELAY
         if File.exists? @fn
@@ -25,6 +26,11 @@ class SuicideManager
       end
     end
   end
+
+  def stop
+    @thread.kill if @thread
+    @thread = nil
+  end
 end
 
 end