summaryrefslogtreecommitdiff
path: root/offlineimap-runner.sh
blob: e4a6f6c5215020dd9cdbb4bd7328e8e57426e41d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/bin/sh

# offlineimap is pretty nifty, and generally does the right thing, and is
# remarkably fault-tolerant, even of it's own code.
# 
# One nifty thing it doesn is to check if an instance of it is already running,
# and to exit and let the original insance do it's thing. That lets us do
# things like put it in a crontab. We wouldn't want to do this if it didn't have
# that feature, because then
#  * If the previous run hadn't finished, things would break
#    I have it run every at m="*/5". 5 minutes is usually plenty of time, but
#    for large attachments, it might not be enough.
#  * If I wanted to run it manually, at say m="*/5+4", if it takes more than a
#    minute to run, then the instance invoked by cron would bork everything.

# As awesome as this is, it has one fatal flaw: an instance hanging.
# This only happens rarely, but I've had an instance of offlineimap invoked by
# cron decided to hang up. After 2 days of recieving suspiciously little email,
# I decided to check if offlineimap was running ok. That instance had hung up,
# not recieving any mail, but preventing cron from starting another instance.
#
# So, here is my workaround: keep track of how many times in a row that we've
# tried to start offlineimap, and it failed. If that number exceeds a specified
# number, then assume the running instance hung, and kill it.

if [ "$1" = '-v' ]; then
	shift;
	msg() { echo "$@"; }
else
	msg() { :; }
fi

# A note on notation:
# the number/limit is the number of failures allowed *before* anything is killed.
# So, if the limit is "1", the first time, it will just pass by. The second
# time, it will see that we've already failed once, so if it's still running,
# kill it.
default_limit=2
limit=${1-$default_limit}
shift

cookie_file="$HOME/.offlineimap.cookie"
offlineimap='offlineimap-exit'

# Try running offlineimap
if $offlineimap "$@"; then
	# Everything went smoothly, remove any record of failures
	msg 'Successfully ran offlineimap'
	msg 'Clearing cookie file'
	echo '0' > "$cookie_file"
else
	# oh noez!
	msg 'offlineimap had an error'
	# we interupt your regularly scheduled panic for a sanity check
	if [ ! -f "$cookie_file" ]; then
		echo '0' > "$cookie_file"
	fi
	# you may now resume panicing
	number=`cat "$cookie_file"`
	echo $(($number+1)) > "$cookie_file"

	msg " has failed $number times (with a limit of $limit)"
	if [ "$number" -ge "$limit" ]; then # kill it!
		killall -9 offlineimap
		# We invoke offlineimap directly, instead of recursing on
		# ourself because if something else is causing it to fail, then
		# we'll fork-bomb
		$offlineimap "$@"
	fi
fi