# Buggy code
def _wait(self, condition, signal, timeout_msg, timeout):
    """
    Wait until condition() is True by running an event loop.

    signal: qt signal that should interrupt the event loop.
    timeout_msg: Message to display in case of a timeout.
    timeout: time in seconds before a timeout
    """
    if condition():
        return

    # Create event loop to wait with
    wait_loop = QEventLoop()
    signal.connect(wait_loop.quit)
    wait_timeout = QTimer()
    wait_timeout.setSingleShot(True)
    wait_timeout.timeout.connect(wait_loop.quit)

    # Wait until the kernel returns the value
    wait_timeout.start(timeout * 1000)
    while not condition():
        if not wait_timeout.isActive():
            signal.disconnect(wait_loop.quit)
            if not condition():
                raise TimeoutError(timeout_msg)
            return
        wait_loop.exec_()

    wait_timeout.stop()
    signal.disconnect(wait_loop.quit)


# Traceback (TimeoutError)
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder\plugins\ipythonconsole\plugin.py", line 1083, in set_spyder_breakpoints
cl.shellwidget.set_spyder_breakpoints()
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder\plugins\ipythonconsole\widgets\debugging.py", line 143, in set_spyder_breakpoints
CONF.get('run', 'breakpoints', {}))
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder_kernels\comms\commbase.py", line 538, in __call__
call_dict, call_data, self._comm_id)
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder\plugins\ipythonconsole\comms\kernelcomm.py", line 130, in _get_call_return_value
with self.comm_channel_manager(comm_id, queue_message=not interrupt):
File "C:\Users\AlexStoll\Anaconda3\lib\contextlib.py", line 81, in __enter__
return next(self.gen)
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder\plugins\ipythonconsole\comms\kernelcomm.py", line 87, in comm_channel_manager
timeout)
File "C:\Users\AlexStoll\Anaconda3\lib\site-packages\spyder\plugins\ipythonconsole\comms\kernelcomm.py", line 168, in _wait
raise TimeoutError(timeout_msg)
TimeoutError: Timeout while waiting for comm port.

# Fixed code
def _wait(self, condition, signal, timeout_msg, timeout):
    """
    Wait until condition() is True by running an event loop.

    signal: qt signal that should interrupt the event loop.
    timeout_msg: Message to display in case of a timeout.
    timeout: time in seconds before a timeout
    """
    # Exit if condition is fulfilled or the kernel is dead.
    if condition():
        return
    if not self.kernel_client.is_alive():
        raise RuntimeError("Kernel is dead")

    # Create event loop to wait with
    wait_loop = QEventLoop()
    wait_timeout = QTimer()
    wait_timeout.setSingleShot(True)

    # Connect signals to stop kernel loop
    wait_timeout.timeout.connect(wait_loop.quit)
    self.kernel_client.hb_channel.kernel_died.connect(wait_loop.quit)
    signal.connect(wait_loop.quit)

    # Wait until the kernel returns the value
    wait_timeout.start(timeout * 1000)
    while not condition():
        if not wait_timeout.isActive():
            signal.disconnect(wait_loop.quit)
            self.kernel_client.hb_channel.kernel_died.disconnect(wait_loop.quit)
            if condition():
                return
            if not self.kernel_client.is_alive():
                raise RuntimeError("Kernel is dead")
            raise TimeoutError(timeout_msg)
        wait_loop.exec_()

    wait_timeout.stop()
    signal.disconnect(wait_loop.quit)
    self.kernel_client.hb_channel.kernel_died.disconnect(wait_loop.quit)