]> git.cworth.org Git - sup/commitdiff
refactor index locking interaction and replace suicidemanager
authorWilliam Morgan <wmorgan-sup@masanjin.net>
Fri, 7 Aug 2009 01:33:19 +0000 (21:33 -0400)
committerWilliam Morgan <wmorgan-sup@masanjin.net>
Fri, 7 Aug 2009 01:33:19 +0000 (21:33 -0400)
Since SIGTERM now works, we have a better way of killing a remote
process than SuicideManager. So replace that with a $die global.
Also refactor the interactive locking code into a separate module
so as not to pollute index.rb with such trivial concerns.

Manifest.txt
bin/sup
bin/sup-add
bin/sup-sync
bin/sup-sync-back
bin/sup-tweak-labels
lib/sup.rb
lib/sup/index.rb
lib/sup/interactive-lock.rb [new file with mode: 0644]
lib/sup/suicide.rb [deleted file]
lib/sup/util.rb

index be633d776e2b1e5165edeac4d7631cf714471207..09d867eb47595a3ad8a1a7e693734e9f201cb983 100644 (file)
@@ -32,6 +32,7 @@ lib/sup/index.rb
 lib/sup/keymap.rb
 lib/sup/label.rb
 lib/sup/logger.rb
+lib/sup/interactive-lock.rb
 lib/sup/maildir.rb
 lib/sup/mbox.rb
 lib/sup/mbox/loader.rb
@@ -67,7 +68,6 @@ lib/sup/poll.rb
 lib/sup/rfc2047.rb
 lib/sup/sent.rb
 lib/sup/source.rb
-lib/sup/suicide.rb
 lib/sup/tagger.rb
 lib/sup/textfield.rb
 lib/sup/thread.rb
diff --git a/bin/sup b/bin/sup
index b87c11223342aefe977b34e99f053ba548a4fc6d..c6556e35b5766f387816d3668f711272b330999a 100755 (executable)
--- a/bin/sup
+++ b/bin/sup
@@ -130,37 +130,14 @@ end
 module_function :start_cursing, :stop_cursing
 
 Index.new
-begin
-  Index.lock
-rescue Index::LockError => e
-  require 'highline'
-
-  h = HighLine.new
-  h.wrap_at = :auto
-  h.say Index.fancy_lock_error_message_for(e)
-
-  case h.ask("Should I ask that process to kill itself? ")
-  when /^\s*y(es)?\s*$/i
-    h.say "Ok, suggesting seppuku..."
-    FileUtils.touch Redwood::SUICIDE_FN
-    sleep SuicideManager::DELAY * 2
-    FileUtils.rm_f Redwood::SUICIDE_FN
-    h.say "Let's try that again."
-    retry
-  else
-    h.say <<EOS
-Ok, giving up. If the process crashed and left a stale lockfile, you
-can fix this by manually deleting #{Index.lockfile}.
-EOS
-    exit
-  end
-end
+Index.lock_interactively or exit
 
 begin
   Redwood::start
   Index.load
 
-  trap("TERM") { |x| SuicideManager.please_die! }
+  $die = false
+  trap("TERM") { |x| $die = true }
   trap("WINCH") { |x| BufferManager.sigwinch_happened! }
 
   if(s = Redwood::SourceManager.source_for DraftManager.source_name)
@@ -212,7 +189,6 @@ begin
 
   unless $opts[:no_threads]
     PollManager.start
-    SuicideManager.start
     Index.start_lock_update_thread
   end
 
@@ -220,7 +196,7 @@ begin
     SearchResultsMode.spawn_from_query $opts[:search]
   end
 
-  until Redwood::exceptions.nonempty? || SuicideManager.die?
+  until Redwood::exceptions.nonempty? || $die
     c = begin
       Ncurses.nonblocking_getch
     rescue Interrupt => e
@@ -319,13 +295,12 @@ begin
     bm.draw_screen
   end
 
-  bm.kill_all_buffers if SuicideManager.die?
+  bm.kill_all_buffers if $die
 rescue Exception => e
   Redwood::record_exception e, "main"
 ensure
   unless $opts[:no_threads]
     PollManager.stop if PollManager.instantiated?
-    SuicideManager.stop if PollManager.instantiated?
     Index.stop_lock_update_thread
   end
 
@@ -335,7 +310,7 @@ ensure
   stop_cursing
   Redwood::log "stopped cursing"
 
-  if SuicideManager.instantiated? && SuicideManager.die?
+  if $die
     Redwood::log "I've been ordered to commit seppuku. I obey!"
   end
 
index 3ab7c4db0a18bf4bdb07bf2b9b7f9af375172e78..64d2890596cd4d5465d57bbc7e8aafdeb2c0c2a5 100755 (executable)
@@ -79,7 +79,7 @@ $terminal.wrap_at = :auto
 Redwood::start
 index = Redwood::Index.new
 
-index.lock_or_die
+index.lock_interactively or exit
 
 begin
   Redwood::SourceManager.load_sources
index 8e37c745873865ccb710ca4bdea68694f02bc590..62e1b67799f9133ca6d5ff07b97875d4f62fbbd2 100755 (executable)
@@ -111,7 +111,7 @@ restored_state =
   end
 
 seen = {}
-index.lock_or_die
+index.lock_interactively or exit
 begin
   index.load
 
index 56ac4eb51c05545e8879c976fcbf8b9c4d695c65..6e66c6b646519afb1b5865a40e336520768ce64d 100755 (executable)
@@ -66,7 +66,7 @@ end
 
 Redwood::start
 index = Redwood::Index.new
-index.lock_or_die
+index.lock_interactively or exit
 
 deleted_fp, spam_fp = nil
 unless opts[:dry_run]
index 8ae5c26f9054c841ad612bdaf29c79f300cab753..eac300ebf866e90ef1f7ac1328713e87126331d6 100755 (executable)
@@ -58,10 +58,12 @@ add_labels = (opts[:add] || "").split(",").map { |l| l.intern }.uniq
 remove_labels = (opts[:remove] || "").split(",").map { |l| l.intern }.uniq
 
 Trollop::die "nothing to do: no labels to add or remove" if add_labels.empty? && remove_labels.empty?
+Trollop::die "no sources specified" if ARGV.empty?
 
 Redwood::start
+index = Redwood::Index.new
+index.lock_interactively or exit
 begin
-  index = Redwood::Index.new
   index.load
 
   source_ids = 
index 54de73f5597f1e2f752f07a00694d39de547880b..cfa93fc6608c13c6c0dd508c0c99267f6bdcb1f6 100644 (file)
@@ -114,7 +114,6 @@ module Redwood
     Redwood::DraftManager.new Redwood::DRAFT_DIR
     Redwood::UpdateManager.new
     Redwood::PollManager.new
-    Redwood::SuicideManager.new Redwood::SUICIDE_FN
     Redwood::CryptoManager.new
     Redwood::UndoManager.new
     Redwood::SourceManager.new
@@ -256,7 +255,6 @@ end
 
 ## now everything else (which can feel free to call Redwood::log at load time)
 require "sup/update"
-require "sup/suicide"
 require "sup/message-chunks"
 require "sup/message"
 require "sup/source"
@@ -266,6 +264,7 @@ require "sup/imap"
 require "sup/person"
 require "sup/account"
 require "sup/thread"
+require "sup/interactive-lock"
 require "sup/index"
 require "sup/textfield"
 require "sup/colormap"
index fb46eb053a02b871923e93281021441414e11683..54ec84325224bce3a0ff75dbd695daf42c3e2b98 100644 (file)
@@ -13,6 +13,8 @@ end
 module Redwood
 
 class BaseIndex
+  include InteractiveLock
+
   class LockError < StandardError
     def initialize h
       @h = h
@@ -54,42 +56,6 @@ class BaseIndex
     @lock_update_thread = nil
   end
 
-  def possibly_pluralize number_of, kind
-    "#{number_of} #{kind}" +
-        if number_of == 1 then "" else "s" end
-  end
-
-  def fancy_lock_error_message_for e
-    secs = (Time.now - e.mtime).to_i
-    mins = secs / 60
-    time =
-      if mins == 0
-        possibly_pluralize secs , "second"
-      else
-        possibly_pluralize mins, "minute"
-      end
-
-    <<EOS
-Error: the sup index is locked by another process! User '#{e.user}' on
-host '#{e.host}' is running #{e.pname} with pid #{e.pid}. The process was alive
-as of #{time} ago.
-EOS
-  end
-
-  def lock_or_die
-    begin
-      lock
-    rescue LockError => e
-      $stderr.puts fancy_lock_error_message_for(e)
-      $stderr.puts <<EOS
-
-You can wait for the process to finish, or, if it crashed and left a
-stale lock file behind, you can manually delete #{@lock.path}.
-EOS
-      exit
-    end
-  end
-
   def unlock
     if @lock && @lock.locked?
       Redwood::log "unlocking #{lockfile}..."
diff --git a/lib/sup/interactive-lock.rb b/lib/sup/interactive-lock.rb
new file mode 100644 (file)
index 0000000..92a5ead
--- /dev/null
@@ -0,0 +1,74 @@
+require 'fileutils'
+
+module Redwood
+
+## wrap a nice interactive layer on top of anything that has a #lock method
+## which throws a LockError which responds to #user, #host, #mtim, #pname, and
+## #pid.
+
+module InteractiveLock
+  def pluralize number_of, kind; "#{number_of} #{kind}" + (number_of == 1 ? "" : "s") end
+
+  def time_ago_in_words time
+    secs = (Time.now - time).to_i
+    mins = secs / 60
+    time = if mins == 0
+      pluralize secs, "second"
+    else
+      pluralize mins, "minute"
+    end
+  end
+
+  DELAY = 5 # seconds
+
+  def lock_interactively stream=$stderr
+    begin
+      Index.lock
+    rescue Index::LockError => e
+      stream.puts <<EOS
+Error: the index is locked by another process! User '#{e.user}' on
+host '#{e.host}' is running #{e.pname} with pid #{e.pid}.
+The process was alive as of at least #{time_ago_in_words e.mtime} ago.
+
+EOS
+      stream.print "Should I ask that process to kill itself (y/n)? "
+      stream.flush
+
+      success = if $stdin.gets =~ /^\s*y(es)?\s*$/i
+        stream.puts "Ok, trying to kill process..."
+
+        begin
+          Process.kill "TERM", e.pid.to_i
+          sleep DELAY
+        rescue Errno::ESRCH # no such process
+          stream.puts "Hm, I couldn't kill it."
+        end
+
+        stream.puts "Let's try that again."
+        begin
+          Index.lock
+        rescue Index::LockError => e
+          stream.puts "I couldn't lock the index. The lockfile might just be stale."
+          stream.print "Should I just remove it and continue? (y/n) "
+          stream.flush
+
+          if $stdin.gets =~ /^\s*y(es)?\s*$/i
+            FileUtils.rm e.path
+
+            stream.puts "Let's try that one more time."
+            begin
+              Index.lock
+              true
+            rescue Index::LockError => e
+            end
+          end
+        end
+      end
+
+      stream.puts "Sorry, couldn't unlock the index." unless success
+      success
+    end
+  end
+end
+
+end
diff --git a/lib/sup/suicide.rb b/lib/sup/suicide.rb
deleted file mode 100644 (file)
index 53f31a5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-module Redwood
-
-class SuicideManager
-  include Singleton
-
-  DELAY = 5
-
-  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 please_die!; @die = true end
-
-  def start
-    @thread = Redwood::reporting_thread("suicide watch") do
-      while true
-        sleep DELAY
-        if File.exists? @fn
-          FileUtils.rm_f @fn
-          @die = true
-        end
-      end
-    end
-  end
-
-  def stop
-    @thread.kill if @thread
-    @thread = nil
-  end
-end
-
-end
index 3f2c901a160823c4229d922fd1c052fa42e6a428..f71094e4d8120bba2d649abc4e3f2465a8977d8d 100644 (file)
@@ -24,6 +24,7 @@ class Lockfile
   def lockinfo_on_disk
     h = load_lock_id IO.read(path)
     h['mtime'] = File.mtime path
+    h['path'] = path
     h
   end