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
 
 rescue Exception => e
   $exception ||= e
 ensure
+  unless $opts[:no_threads]
+    PollManager.stop
+    SuicideManager.stop
+    Index.stop_lock_update_thread
+  end
+
   Redwood::finish
   stop_cursing
 
 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
 
   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
   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?
 
   end
 
   def start_lock_update_thread
-    Redwood::reporting_thread do
+    @lock_update_thread = Redwood::reporting_thread do
       while true
         sleep 30
         @lock.touch_yourself
     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
       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
 
 
   def initialize
     @mutex = Mutex.new
+    @thread = nil
     @last_poll = nil
     
     self.class.i_am_the_instance self
     [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
     end
   end
 
+  def stop
+    @thread.kill if @thread
+    @thread = nil
+  end
+
   def do_poll
     total_num = total_numi = 0
     @mutex.synchronize do
 
   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
       end
     end
   end
+
+  def stop
+    @thread.kill if @thread
+    @thread = nil
+  end
 end
 
 end