Spawn a managed thread to run ``fn`` on behalf of an extension.
        The passed `identifier` will be included in logs related to this
        thread, and otherwise defaults to `fn.__name__`, if it is set.

        Any uncaught errors inside ``fn`` cause the container to be killed.

        It is the caller's responsibility to terminate their spawned threads.
        Threads are killed automatically if they are still running after
        all extensions are stopped during :meth:`ServiceContainer.stop`.

        Extensions should delegate all thread spawning to the container.

def spawn_managed_thread(self, fn, identifier=None):
        """ Spawn a managed thread to run ``fn`` on behalf of an extension.
        The passed `identifier` will be included in logs related to this
        thread, and otherwise defaults to `fn.__name__`, if it is set.

        Any uncaught errors inside ``fn`` cause the container to be killed.

        It is the caller's responsibility to terminate their spawned threads.
        Threads are killed automatically if they are still running after
        all extensions are stopped during :meth:`ServiceContainer.stop`.

        Extensions should delegate all thread spawning to the container.
        """
        if identifier is None:
            identifier = getattr(fn, '__name__', "<unknown>")

        gt = eventlet.spawn(fn)
        self._managed_threads[gt] = identifier
        gt.link(self._handle_managed_thread_exited, identifier)
        return gt