[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
This commit is contained in:
Calum Lind 2019-06-05 13:38:33 +01:00
parent 4212bd6800
commit be74d96c6a
1 changed files with 10 additions and 1 deletions

View File

@ -18,6 +18,7 @@ This should typically only be used by the Core. Plugins should utilize the
from __future__ import unicode_literals from __future__ import unicode_literals
import logging import logging
import types
from twisted.internet import reactor from twisted.internet import reactor
@ -124,7 +125,15 @@ class AlertManager(component.Component):
for handler in self.handlers[alert_type]: for handler in self.handlers[alert_type]:
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):
log.debug('Handling alert: %s', alert_type) 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): def set_alert_queue_size(self, queue_size):
"""Sets the maximum size of the libtorrent alert queue""" """Sets the maximum size of the libtorrent alert queue"""