[or-cvs] r17051: {weather} Add safeRelease() as a method to ensure that we always relea (weather/trunk)
ioerror at seul.org
ioerror at seul.org
Thu Oct 9 03:56:30 UTC 2008
Author: ioerror
Date: 2008-10-08 23:56:29 -0400 (Wed, 08 Oct 2008)
New Revision: 17051
Modified:
weather/trunk/poll.py
weather/trunk/weather.py
Log:
Add safeRelease() as a method to ensure that we always release the lock on the database, even if we may have tried to release it before. Also, I think this fixes a bug in GET where we would attempt to acquire a lock and possibly return without a proper release(). Lots of refactoring to ensure that we try: ... finally: gdbm_lock.release() whenever we have a locking issue with the database. I do not believe that we need this for the antispam locking code... yet...
Modified: weather/trunk/poll.py
===================================================================
--- weather/trunk/poll.py 2008-10-08 10:47:23 UTC (rev 17050)
+++ weather/trunk/poll.py 2008-10-09 03:56:29 UTC (rev 17051)
@@ -14,6 +14,7 @@
from config import authenticator, URLbase, weather_email, failure_threshold
from config import poll_period, ping_targets, weather_storage
from weather import parse_subscriptions
+from weather import safeRelease
# Lets debug this
import traceback
@@ -152,18 +153,22 @@
if not self.tp.test():
return False
print 'Timestamp', datetime.now().isoformat('-')
- self.gdbm_lock.acquire()
- node = self.subscriptions.firstkey()
- while node != None:
- # nodes stay in the subscription db even if nobody is subscribed to them
- # anymore
- if self.subscriptions[node] != "":
- self.gdbm_lock.release()
- self.ping(node) # this is time consuming ; don't hold the lock
+
+ try:
self.gdbm_lock.acquire()
+ node = self.subscriptions.firstkey()
+ while node != None:
+ # nodes stay in the subscription db even if nobody is subscribed to them
+ # anymore
+ if self.subscriptions[node] != "":
+ self.gdbm_lock.release()
+ self.ping(node) # this is time consuming ; don't hold the lock
+ self.gdbm_lock.acquire()
+ node = self.subscriptions.nextkey(node)
- node = self.subscriptions.nextkey(node)
- self.gdbm_lock.release()
+ finally:
+ safeRelease(self.gdbm_lock)
+
#del self.tp # this minimises the chance of confusion a local tor control
# port crash with a remote node being down
if debug: print "Ping_all finished"
@@ -230,9 +235,11 @@
# envelope header.
s = smtplib.SMTP()
s.connect()
- self.gdbm_lock.acquire()
- list = parse_subscriptions(node,self.subscriptions)
- self.gdbm_lock.release()
+ try:
+ self.gdbm_lock.acquire()
+ list = parse_subscriptions(node,self.subscriptions)
+ finally:
+ safeRelease(self.gdbm_lock)
for address, unsub_token in list:
unsub_url = URLbase+"/unsubscribe/" + unsub_token
Modified: weather/trunk/weather.py
===================================================================
--- weather/trunk/weather.py 2008-10-08 10:47:23 UTC (rev 17050)
+++ weather/trunk/weather.py 2008-10-09 03:56:29 UTC (rev 17051)
@@ -25,6 +25,13 @@
'/unsubscribe/(.*)', 'unsubscribe'
)
+
+def safeRelease(gdbm_lock):
+ try:
+ gdbm_lock.release()
+ except AssertionError:
+ pass
+
if apache_fcgi:
web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
@@ -173,27 +180,32 @@
return True
def already_subscribed(self, address, node):
- gdbm_lock.acquire()
-
try:
- words = subscriptions[node].split()
- if address in words:
- already = True
- else:
- already = False
- except KeyError:
- already = False
+ gdbm_lock.acquire()
- gdbm_lock.release()
- return already
+ try:
+ words = subscriptions[node].split()
+ if address in words:
+ already = True
+ else:
+ already = False
+ except KeyError:
+ already = False
+
+ finally:
+ gdbm_lock.release()
+ return already
def send_confirmation_email(self, address, node):
authstring = randstring()
- gdbm_lock.acquire()
- requests[authstring] = address + " " + node
- gdbm_lock.release()
+ try:
+ gdbm_lock.acquire()
+ requests[authstring] = address + " " + node
+ finally:
+ gdbm_lock.release()
+
if dummy_testing:
print "gotcha"
return True
@@ -283,36 +295,41 @@
web.header('content-type', 'text/html')
print "<html>"
if debug: print "checking confirmation..."
- gdbm_lock.acquire()
- if not requests.has_key(authstring):
- print "Error in subscription request!"
- gdbm_lock.release()
- return 0
+ try:
+ gdbm_lock.acquire()
- email, node = requests[authstring].split()
+ if not requests.has_key(authstring):
+ print "Error in subscription request!"
+ gdbm_lock.release()
+ return 0
- # We want a single link in every outgoing email that will unsubscribe that
- # user. But we don't want to generate a new database entry every time
- # an email gets sent. So do it now, and remember the token.
- unsub_authstring = randstring()
- subscription = email + " " + node + " " + unsub_authstring
- unsubscriptions[unsub_authstring] = subscription
- subscription2 = email + " " + unsub_authstring
- if subscriptions.has_key(node):
- subscriptions[node] += " " +subscription2
- else:
- subscriptions[node] = subscription2
- url = web.ctx.homedomain + "/unsubscribe/" + unsub_authstring
- print "Succesfully subscribed <tt>", email,
- print "</tt> to weather reports about Tor node", node
- print "<p>You can unsubscribe at any time by clicking on the following link:"
- print '<p><a href="' + url + '">' + url + '</a>'
- print '<p>(you will be reminded of it in each weather report we send)'
-
- del(requests[authstring])
- subscriptions.sync()
- gdbm_lock.release()
+ email, node = requests[authstring].split()
+
+ # We want a single link in every outgoing email that will unsubscribe that
+ # user. But we don't want to generate a new database entry every time
+ # an email gets sent. So do it now, and remember the token.
+ unsub_authstring = randstring()
+ subscription = email + " " + node + " " + unsub_authstring
+ unsubscriptions[unsub_authstring] = subscription
+ subscription2 = email + " " + unsub_authstring
+ if subscriptions.has_key(node):
+ subscriptions[node] += " " +subscription2
+ else:
+ subscriptions[node] = subscription2
+ url = web.ctx.homedomain + "/unsubscribe/" + unsub_authstring
+ print "Succesfully subscribed <tt>", email,
+ print "</tt> to weather reports about Tor node", node
+ print "<p>You can unsubscribe at any time by clicking on the following link:"
+ print '<p><a href="' + url + '">' + url + '</a>'
+ print '<p>(you will be reminded of it in each weather report we send)'
+
+ del(requests[authstring])
+ subscriptions.sync()
+
+ finally:
+ safeRelease(gdbm_lock)
+
# okay now slacken antispam watch
antispam_lock.acquire()
if antispam.has_key(web.ctx.ip):
@@ -320,27 +337,30 @@
if antispam[web.ctx.ip] >= antispam_max:
del antispam[web.ctx.ip]
antispam_lock.release()
-
class unsubscribe:
def GET(self,authstring):
web.header('content-type', 'text/html')
- gdbm_lock.acquire()
- if not unsubscriptions.has_key(authstring):
- print "Invalid unsubscription request!"
- print unsubscriptions
- return 0
+ try:
+ gdbm_lock.acquire()
+ if not unsubscriptions.has_key(authstring):
+ print "Invalid unsubscription request!"
+ print unsubscriptions
+ gdbm_lock.release()
+ return 0
- email, node, _ = unsubscriptions[authstring].split()
+ email, node, _ = unsubscriptions[authstring].split()
- delete_sub ((email, authstring), subscriptions, node)
- #subscriptions[node].remove((email,authstring))
- print "<html>Succesfully unsubscribed <tt>", email,
- print "</tt> from weather reports about Tor node", node, "</html>"
- del (unsubscriptions[authstring])
- gdbm_lock.release()
+ delete_sub ((email, authstring), subscriptions, node)
+ #subscriptions[node].remove((email,authstring))
+ print "<html>Succesfully unsubscribed <tt>", email,
+ print "</tt> from weather reports about Tor node", node, "</html>"
+ del (unsubscriptions[authstring])
+ finally:
+ safeRelease(gdbm_lock)
+
class AntispamRelaxer(threading.Thread):
"Prevent long term accretion of antispam counts."
timescale = 24 * 3600 # sleep for up to a day
More information about the tor-commits
mailing list