From be74d96c6a665b18284d2a470eefdd1e7cde8527 Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Wed, 5 Jun 2019 13:38:33 +0100 Subject: [PATCH] [Core] Copy lt alerts to avoid segfaults Changes in libtorrent 1.1 mean that alerts are no longer allowed to be accessed after the next call to pop_alerts. > It is safe to call pop_alerts from multiple different threads, as long as the alerts themselves are not accessed once another thread calls pop_alerts. Doing this requires manual synchronization between the popping threads. The solution is to copy the alert attributes and pass that to the handlers. Refs: https://github.com/arvidn/libtorrent/issues/2779 #3159 --- deluge/core/alertmanager.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/deluge/core/alertmanager.py b/deluge/core/alertmanager.py index 04e429ea5..bf9f6b4c5 100644 --- a/deluge/core/alertmanager.py +++ b/deluge/core/alertmanager.py @@ -18,6 +18,7 @@ This should typically only be used by the Core. Plugins should utilize the from __future__ import unicode_literals import logging +import types from twisted.internet import reactor @@ -124,7 +125,15 @@ class AlertManager(component.Component): for handler in self.handlers[alert_type]: if log.isEnabledFor(logging.DEBUG): log.debug('Handling alert: %s', alert_type) - self.delayed_calls.append(reactor.callLater(0, handler, alert)) + # Copy alert attributes + alert_copy = types.SimpleNamespace( + **{ + attr: getattr(alert, attr) + for attr in dir(alert) + if not attr.startswith('__') + } + ) + self.delayed_calls.append(reactor.callLater(0, handler, alert_copy)) def set_alert_queue_size(self, queue_size): """Sets the maximum size of the libtorrent alert queue"""