3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-27 21:19:31 +01:00

Revert "relay: add locks in db read/writes (thread safety)"

Unfortunately, this made relay prone to freezing the entire PyLink server.

This reverts commit 2b4943a780.
This commit is contained in:
James Lu 2017-05-04 18:50:42 -07:00
parent 1358fedca6
commit d51c399351

View File

@ -13,7 +13,6 @@ relayusers = defaultdict(dict)
relayservers = defaultdict(dict) relayservers = defaultdict(dict)
spawnlocks = defaultdict(threading.RLock) spawnlocks = defaultdict(threading.RLock)
spawnlocks_servers = defaultdict(threading.RLock) spawnlocks_servers = defaultdict(threading.RLock)
db_lock = threading.RLock()
dbname = utils.getDatabaseName('pylinkrelay') dbname = utils.getDatabaseName('pylinkrelay')
datastore = structures.PickleDataStore('pylinkrelay', dbname) datastore = structures.PickleDataStore('pylinkrelay', dbname)
@ -34,11 +33,9 @@ def initialize_all(irc):
# which would break connections. # which would break connections.
world.started.wait(2) world.started.wait(2)
with db_lock:
for chanpair, entrydata in db.items(): for chanpair, entrydata in db.items():
# Iterate over all the channels stored in our relay links DB. # Iterate over all the channels stored in our relay links DB.
network, channel = chanpair network, channel = chanpair
# Initialize each relay channel on their home network, and on every linked one too. # Initialize each relay channel on their home network, and on every linked one too.
initialize_channel(irc, channel) initialize_channel(irc, channel)
for link in entrydata['links']: for link in entrydata['links']:
@ -414,7 +411,6 @@ def get_orig_user(irc, user, targetirc=None):
def get_relay(chanpair): def get_relay(chanpair):
"""Finds the matching relay entry name for the given (network name, channel) """Finds the matching relay entry name for the given (network name, channel)
pair, if one exists.""" pair, if one exists."""
with db_lock:
if chanpair in db: # This chanpair is a shared channel; others link to it if chanpair in db: # This chanpair is a shared channel; others link to it
return chanpair return chanpair
# This chanpair is linked *to* a remote channel # This chanpair is linked *to* a remote channel
@ -433,7 +429,6 @@ def get_remote_channel(irc, remoteirc, channel):
if chanpair[0] == remotenetname: if chanpair[0] == remotenetname:
return chanpair[1] return chanpair[1]
else: else:
with db_lock:
for link in db[chanpair]['links']: for link in db[chanpair]['links']:
if link[0] == remotenetname: if link[0] == remotenetname:
return link[1] return link[1]
@ -447,7 +442,6 @@ def initialize_channel(irc, channel):
log.debug('(%s) relay.initialize_channel: relay pair found to be %s', irc.name, relay) log.debug('(%s) relay.initialize_channel: relay pair found to be %s', irc.name, relay)
queued_users = [] queued_users = []
if relay: if relay:
with db_lock:
all_links = db[relay]['links'].copy() all_links = db[relay]['links'].copy()
all_links.update((relay,)) all_links.update((relay,))
log.debug('(%s) relay.initialize_channel: all_links: %s', irc.name, all_links) log.debug('(%s) relay.initialize_channel: all_links: %s', irc.name, all_links)
@ -531,9 +525,7 @@ def check_claim(irc, channel, sender, chanobj=None):
sender_modes = get_prefix_modes(irc, irc, channel, sender, mlist=mlist) sender_modes = get_prefix_modes(irc, irc, channel, sender, mlist=mlist)
log.debug('(%s) relay.check_claim: sender modes (%s/%s) are %s (mlist=%s)', irc.name, log.debug('(%s) relay.check_claim: sender modes (%s/%s) are %s (mlist=%s)', irc.name,
sender, channel, sender_modes, mlist) sender, channel, sender_modes, mlist)
# XXX: stop hardcoding modes to check for and support mlist in isHalfopPlus and friends # XXX: stop hardcoding modes to check for and support mlist in isHalfopPlus and friends
with db_lock:
return (not relay) or irc.name == relay[0] or not db[relay]['claim'] or \ return (not relay) or irc.name == relay[0] or not db[relay]['claim'] or \
irc.name in db[relay]['claim'] or \ irc.name in db[relay]['claim'] or \
any([mode in sender_modes for mode in ('y', 'q', 'a', 'o', 'h')]) \ any([mode in sender_modes for mode in ('y', 'q', 'a', 'o', 'h')]) \
@ -1511,7 +1503,6 @@ def handle_disconnect(irc, numeric, command, args):
announcement = conf.conf.get('relay', {}).get('disconnect_announcement') announcement = conf.conf.get('relay', {}).get('disconnect_announcement')
log.debug('(%s) relay: last connection successful: %s', irc.name, args.get('was_successful')) log.debug('(%s) relay: last connection successful: %s', irc.name, args.get('was_successful'))
if announcement and args.get('was_successful'): if announcement and args.get('was_successful'):
with db_lock:
for chanpair, entrydata in db.items(): for chanpair, entrydata in db.items():
log.debug('(%s) relay: Looking up %s', irc.name, chanpair) log.debug('(%s) relay: Looking up %s', irc.name, chanpair)
if chanpair[0] == irc.name: if chanpair[0] == irc.name:
@ -1601,7 +1592,6 @@ def create(irc, source, args):
creator = irc.getHostmask(source) creator = irc.getHostmask(source)
# Create the relay database entry with the (network name, channel name) # Create the relay database entry with the (network name, channel name)
# pair - this is just a dict with various keys. # pair - this is just a dict with various keys.
with db_lock:
db[(irc.name, channel)] = {'claim': [irc.name], 'links': set(), db[(irc.name, channel)] = {'claim': [irc.name], 'links': set(),
'blocked_nets': set(), 'creator': creator, 'blocked_nets': set(), 'creator': creator,
'ts': time.time()} 'ts': time.time()}
@ -1614,7 +1604,6 @@ def stop_relay(entry):
"""Internal function to deinitialize a relay link and its leaves.""" """Internal function to deinitialize a relay link and its leaves."""
network, channel = entry network, channel = entry
# Iterate over all the channel links and deinitialize them. # Iterate over all the channel links and deinitialize them.
with db_lock:
for link in db[entry]['links']: for link in db[entry]['links']:
remove_channel(world.networkobjects.get(link[0]), link[1]) remove_channel(world.networkobjects.get(link[0]), link[1])
remove_channel(world.networkobjects.get(network), channel) remove_channel(world.networkobjects.get(network), channel)
@ -1646,8 +1635,6 @@ def destroy(irc, source, args):
permissions.checkPermissions(irc, source, ['relay.destroy.remote']) permissions.checkPermissions(irc, source, ['relay.destroy.remote'])
entry = (network, channel) entry = (network, channel)
with db_lock:
if entry in db: if entry in db:
stop_relay(entry) stop_relay(entry)
del db[entry] del db[entry]
@ -1675,7 +1662,6 @@ def purge(irc, source, args):
count = 0 count = 0
with db_lock:
for entry in db.copy(): for entry in db.copy():
# Entry was owned by the target network; remove it # Entry was owned by the target network; remove it
if entry[0] == network: if entry[0] == network:
@ -1751,7 +1737,6 @@ def link(irc, source, args):
return return
try: try:
with db_lock:
entry = db[(remotenet, channel)] entry = db[(remotenet, channel)]
except KeyError: except KeyError:
irc.error('No such relay %r exists.' % args.channel) irc.error('No such relay %r exists.' % args.channel)
@ -1826,14 +1811,12 @@ def delink(irc, source, args):
"network).") "network).")
return return
else: else:
with db_lock:
for link in db[entry]['links'].copy(): for link in db[entry]['links'].copy():
if link[0] == remotenet: if link[0] == remotenet:
remove_channel(world.networkobjects.get(remotenet), link[1]) remove_channel(world.networkobjects.get(remotenet), link[1])
db[entry]['links'].remove(link) db[entry]['links'].remove(link)
else: else:
remove_channel(irc, channel) remove_channel(irc, channel)
with db_lock:
db[entry]['links'].remove((irc.name, channel)) db[entry]['links'].remove((irc.name, channel))
irc.reply('Done.') irc.reply('Done.')
log.info('(%s) relay: Channel %s delinked from %s%s by %s.', irc.name, log.info('(%s) relay: Channel %s delinked from %s%s by %s.', irc.name,
@ -1871,7 +1854,6 @@ def linked(irc, source, args):
irc.reply("Showing channels linked to %s:" % net, private=True) irc.reply("Showing channels linked to %s:" % net, private=True)
# Sort the list of shared channels when displaying # Sort the list of shared channels when displaying
with db_lock:
for k, v in sorted(db.items()): for k, v in sorted(db.items()):
# Skip if we're filtering by network and the network given isn't relayed # Skip if we're filtering by network and the network given isn't relayed
@ -1948,8 +1930,6 @@ def linkacl(irc, source, args):
if not relay: if not relay:
irc.error('No such relay %r exists.' % channel) irc.error('No such relay %r exists.' % channel)
return return
with db_lock:
if cmd == 'list': if cmd == 'list':
permissions.checkPermissions(irc, source, ['relay.linkacl.view']) permissions.checkPermissions(irc, source, ['relay.linkacl.view'])
s = 'Blocked networks for \x02%s\x02: \x02%s\x02' % (channel, ', '.join(db[relay]['blocked_nets']) or '(empty)') s = 'Blocked networks for \x02%s\x02: \x02%s\x02' % (channel, ', '.join(db[relay]['blocked_nets']) or '(empty)')
@ -2076,7 +2056,6 @@ def claim(irc, source, args):
# We override get_relay() here to limit the search to the current network. # We override get_relay() here to limit the search to the current network.
relay = (irc.name, channel) relay = (irc.name, channel)
with db_lock:
if relay not in db: if relay not in db:
irc.error('No relay %r exists on this network (this command must be run on the ' irc.error('No relay %r exists on this network (this command must be run on the '
'network this channel was created on).' % channel) 'network this channel was created on).' % channel)
@ -2087,9 +2066,6 @@ def claim(irc, source, args):
except IndexError: # No networks given. except IndexError: # No networks given.
irc.reply('Channel \x02%s\x02 is claimed by: %s' % irc.reply('Channel \x02%s\x02 is claimed by: %s' %
(channel, ', '.join(claimed) or '\x1D(none)\x1D')) (channel, ', '.join(claimed) or '\x1D(none)\x1D'))
else:
if nets == '-' or not nets:
claimed = set()
else: else:
claimed = set(nets.split(',')) claimed = set(nets.split(','))
db[relay]["claim"] = claimed db[relay]["claim"] = claimed