# Buggy code
def monitor_downloads(self, dslist):
    # Monitor downloads with anonymous flag set, and build rendezvous/introduction points when needed.
    new_states = {}
    hops = {}

    for ds in dslist:
        download = ds.get_download()
        if download.get_hops() > 0:
            # Convert the real infohash to the infohash used for looking up introduction points
            real_info_hash = download.get_def().get_infohash()
            info_hash = self.get_lookup_info_hash(real_info_hash)
            hops[info_hash] = download.get_hops()
            new_states[info_hash] = ds.get_status()

    self.hops = hops

    for info_hash in set(new_states.keys() + self.download_states.keys()):
        new_state = new_states.get(info_hash, None)
        old_state = self.download_states.get(info_hash, None)
        state_changed = new_state != old_state

        # If the introducing circuit does not exist anymore or timed out: Build a new circuit
        if info_hash in self.infohash_ip_circuits:
            for circuit_id, time_created in self.infohash_ip_circuits[info_hash]:
                if (
                    circuit_id not in self.my_intro_points
                    and time_created < time.time() - 30
                ):
                    self.infohash_ip_circuits[info_hash].remove(
                        (circuit_id, time_created)
                    )
                    if self.notifier:
                        self.notifier.notify(
                            NTFY_TUNNEL,
                            NTFY_IP_RECREATE,
                            circuit_id,
                            info_hash.encode("hex")[:6],
                        )
                    self.tunnel_logger.info(
                        "Recreate the introducing circuit for %s"
                        % info_hash.encode("hex")
                    )
                    self.create_introduction_point(info_hash)

        time_elapsed = time.time() - self.last_dht_lookup.get(info_hash, 0)
        force_dht_lookup = time_elapsed >= self.settings.dht_lookup_interval
        if (state_changed or force_dht_lookup) and (
            new_state == DLSTATUS_SEEDING or new_state == DLSTATUS_DOWNLOADING
        ):
            self.tunnel_logger.info(
                "Do dht lookup to find hidden services peers for %s"
                % info_hash.encode("hex")
            )
            self.do_dht_lookup(info_hash)

        if state_changed and new_state == DLSTATUS_SEEDING:
            self.create_introduction_point(info_hash)

        elif state_changed and new_state in [DLSTATUS_STOPPED, None]:
            if info_hash in self.infohash_pex:
                self.infohash_pex.pop(info_hash)

            for cid, info_hash_hops in self.my_download_points.items():
                if info_hash_hops[0] == info_hash:
                    self.remove_circuit(cid, "download stopped", destroy=True)

            for cid, info_hash_list in self.my_intro_points.items():
                for i in xrange(len(info_hash_list) - 1, -1, -1):
                    if info_hash_list[i] == info_hash:
                        info_hash_list.pop(i)

                if len(info_hash_list) == 0:
                    self.remove_circuit(cid, "all downloads stopped", destroy=True)

    self.download_states = new_states


# Traceback (RuntimeError)
Traceback (most recent call last):
File "TriblerGUI\event_request_manager.py", line 92, in on_read_data
RuntimeError: Unhandled Error
Traceback (most recent call last):
File "lib\multiprocessing\process.py", line 114, in run

File "TriblerGUI\core_manager.py", line 63, in start_tribler_core

File "lib\site-packages\twisted\internet\base.py", line 1195, in run

File "lib\site-packages\twisted\internet\base.py", line 1204, in mainLoop

--- <exception caught here> ---
File "lib\site-packages\twisted\internet\base.py", line 798, in runUntilCurrent

File "Tribler\community\tunnel\hidden_community.py", line 250, in monitor_downloads

File "Tribler\community\tunnel\hidden_community.py", line 619, in create_introduction_point

exceptions.AttributeError: 'NoneType' object has no attribute 'add_peer'

# Fixed code
def monitor_downloads(self, dslist):
    # Monitor downloads with anonymous flag set, and build rendezvous/introduction points when needed.
    new_states = {}
    hops = {}

    for ds in dslist:
        download = ds.get_download()
        if download.get_hops() > 0:
            # Convert the real infohash to the infohash used for looking up introduction points
            real_info_hash = download.get_def().get_infohash()
            info_hash = self.get_lookup_info_hash(real_info_hash)
            hops[info_hash] = download.get_hops()
            new_states[info_hash] = ds.get_status()

    self.hops = hops

    for info_hash in set(new_states.keys() + self.download_states.keys()):
        new_state = new_states.get(info_hash, None)
        old_state = self.download_states.get(info_hash, None)
        state_changed = new_state != old_state

        # Stop creating introduction points if the download doesn't exist anymore
        if info_hash in self.infohash_ip_circuits and new_state is None:
            del self.infohash_ip_circuits[info_hash]

        # If the introducing circuit does not exist anymore or timed out: Build a new circuit
        if info_hash in self.infohash_ip_circuits:
            for circuit_id, time_created in self.infohash_ip_circuits[info_hash]:
                if (
                    circuit_id not in self.my_intro_points
                    and time_created < time.time() - 30
                ):
                    self.infohash_ip_circuits[info_hash].remove(
                        (circuit_id, time_created)
                    )
                    if self.notifier:
                        self.notifier.notify(
                            NTFY_TUNNEL,
                            NTFY_IP_RECREATE,
                            circuit_id,
                            info_hash.encode("hex")[:6],
                        )
                    self.tunnel_logger.info(
                        "Recreate the introducing circuit for %s"
                        % info_hash.encode("hex")
                    )
                    self.create_introduction_point(info_hash)

        time_elapsed = time.time() - self.last_dht_lookup.get(info_hash, 0)
        force_dht_lookup = time_elapsed >= self.settings.dht_lookup_interval
        if (state_changed or force_dht_lookup) and (
            new_state == DLSTATUS_SEEDING or new_state == DLSTATUS_DOWNLOADING
        ):
            self.tunnel_logger.info(
                "Do dht lookup to find hidden services peers for %s"
                % info_hash.encode("hex")
            )
            self.do_dht_lookup(info_hash)

        if state_changed and new_state == DLSTATUS_SEEDING:
            self.create_introduction_point(info_hash)

        elif state_changed and new_state in [DLSTATUS_STOPPED, None]:
            if info_hash in self.infohash_pex:
                self.infohash_pex.pop(info_hash)

            for cid, info_hash_hops in self.my_download_points.items():
                if info_hash_hops[0] == info_hash:
                    self.remove_circuit(cid, "download stopped", destroy=True)

            for cid, info_hash_list in self.my_intro_points.items():
                for i in xrange(len(info_hash_list) - 1, -1, -1):
                    if info_hash_list[i] == info_hash:
                        info_hash_list.pop(i)

                if len(info_hash_list) == 0:
                    self.remove_circuit(cid, "all downloads stopped", destroy=True)

    self.download_states = new_states