p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[2].gsub(/^\s+/, "")
p.changes = p.paragraphs_of('History.txt', 0..0).join("\n\n")
p.email = "wmorgan-sup@masanjin.net"
- p.extra_deps = [['ferret', '>= 0.10.13'], ['ncurses', '>= 0.9.1'], ['rmail', '>= 0.17'], 'highline', 'net-ssh', ['trollop', '>= 1.5']]
+ p.extra_deps = [['ferret', '>= 0.10.13'], ['ncurses', '>= 0.9.1'], ['rmail', '>= 0.17'], 'highline', 'net-ssh', ['trollop', '>= 1.5'], 'lockfile']
end
rule 'ss?.png' => 'ss?-small.png' do |t|
require 'rubygems'
require 'ncurses'
+require 'fileutils'
require 'trollop'
require "sup"
end
module_function :start_cursing, :stop_cursing
+begin
+ Redwood::lock
+rescue LockError => e
+ require 'highline'
+ h = HighLine.new
+ h.say <<EOS
+Error: sup is already running! User #{e.user} on host #{e.host} was running sup
+with pid #{e.pid} as of #{e.time}.
+EOS
+
+ case h.ask("Should I try and kill that process? ")
+ when /^\s*y\s*$/i
+ h.say "Ok, suggesting sepuku..."
+ 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 "Ok, see you later."
+ exit
+ end
+end
+
Redwood::start
Index.new.load
imode.load_threads :num => ibuf.content_height, :when_done => lambda { reporting_thread { sleep 1; PollManager.poll } }
- PollManager.start_thread unless $opts[:no_threads]
+ unless $opts[:no_threads]
+ PollManager.start_thread
+ SuicideManager.start_thread
+ end
until $exception
bm.draw_screen
ensure
Redwood::finish
stop_cursing
- if $exception
- Redwood::log "oh crap, an exception"
- else
+
+ case $exception
+ when SuicideException
+ Redwood::log "I've been asked to commit sepuku. I obey!"
+ exit
+ when nil
Redwood::log "good night, sweet prince!"
+ Index.save
+ else
+ Redwood::log "oh crap, an exception"
end
-end
-Index.save unless $exception # TODO: think about this
+ Redwood::unlock
+end
if $exception
$stderr.puts <<EOS
require 'zlib'
require 'thread'
require 'fileutils'
+require 'lockfile'
+
+## time for some monkeypatching!
+class Lockfile
+ def gen_lock_id
+ Hash[
+ 'host' => "#{ Socket.gethostname }",
+ 'pid' => "#{ Process.pid }",
+ 'ppid' => "#{ Process.ppid }",
+ 'time' => timestamp,
+ 'user' => ENV["USER"]
+ ]
+ end
+
+ def dump_lock_id lock_id = @lock_id
+ "host: %s\npid: %s\nppid: %s\ntime: %s\nuser: %s\n" %
+ lock_id.values_at('host','pid','ppid','time','user')
+ end
+
+ def lockinfo_on_disk
+ load_lock_id IO.read(path)
+ end
+end
class Object
## this is for debugging purposes because i keep calling #id on the
end
end
+class LockError < StandardError
+ def initialize h
+ super ""
+ @h = h
+ end
+
+ def method_missing m; @h[m.to_s] end
+end
+
class Module
def yaml_properties *props
props = props.map { |p| p.to_s }
CONTACT_FN = File.join(BASE_DIR, "contacts.txt")
DRAFT_DIR = File.join(BASE_DIR, "drafts")
SENT_FN = File.join(BASE_DIR, "sent.mbox")
+ LOCK_FN = File.join(BASE_DIR, "lock")
+ SUICIDE_FN = File.join(BASE_DIR, "please-kill-yourself")
YAML_DOMAIN = "masanjin.net"
YAML_DATE = "2006-10-01"
File.open("sup-exception-log.txt", "w") do |f|
f.puts "--- #{e.class.name} at #{Time.now}"
f.puts e.message, e.backtrace
- end
+ end unless e.is_a? SuicideException
$exception ||= e
raise
end
Redwood::DraftManager.new Redwood::DRAFT_DIR
Redwood::UpdateManager.new
Redwood::PollManager.new
+ Redwood::SuicideManager.new Redwood::SUICIDE_FN
end
def finish
Redwood::BufferManager.deinstantiate!
end
+ def lock
+ FileUtils.rm_f SUICIDE_FN
+
+ Redwood::log "locking #{LOCK_FN}..."
+ $lock = Lockfile.new LOCK_FN, :retries => 0
+ begin
+ $lock.lock
+ rescue Lockfile::MaxTriesLockError
+ raise LockError, $lock.lockinfo_on_disk
+ end
+ end
+
+ def unlock
+ Redwood::log "unlocking #{LOCK_FN}..."
+ $lock.unlock if $lock
+ end
+
## not really a good place for this, so I'll just dump it here.
def report_broken_sources opts={}
return unless BufferManager.instantiated?
end
end
- module_function :save_yaml_obj, :load_yaml_obj, :start, :finish, :report_broken_sources
+ module_function :save_yaml_obj, :load_yaml_obj, :start, :finish,
+ :lock, :unlock, :report_broken_sources
end
## set up default configuration file
require "sup/util"
require "sup/update"
+require "sup/suicide"
require "sup/message"
require "sup/source"
require "sup/mbox"