# Buggy code
def join(
    self,
    timeout=None,
    propagate=True,
    interval=0.5,
    callback=None,
    no_ack=True,
    on_message=None,
    disable_sync_subtasks=True,
    on_interval=None,
):
    """Gather the results of all tasks as a list in order.

    Note:
        This can be an expensive operation for result store
        backends that must resort to polling (e.g., database).

        You should consider using :meth:`join_native` if your backend
        supports it.

    Warning:
        Waiting for tasks within a task may lead to deadlocks.
        Please see :ref:`task-synchronous-subtasks`.

    Arguments:
        timeout (float): The number of seconds to wait for results
            before the operation times out.
        propagate (bool): If any of the tasks raises an exception,
            the exception will be re-raised when this flag is set.
        interval (float): Time to wait (in seconds) before retrying to
            retrieve a result from the set.  Note that this does not have
            any effect when using the amqp result store backend,
            as it does not use polling.
        callback (Callable): Optional callback to be called for every
            result received.  Must have signature ``(task_id, value)``
            No results will be returned by this function if a callback
            is specified.  The order of results is also arbitrary when a
            callback is used.  To get access to the result object for
            a particular id you'll have to generate an index first:
            ``index = {r.id: r for r in gres.results.values()}``
            Or you can create new result objects on the fly:
            ``result = app.AsyncResult(task_id)`` (both will
            take advantage of the backend cache anyway).
        no_ack (bool): Automatic message acknowledgment (Note that if this
            is set to :const:`False` then the messages
            *will not be acknowledged*).
        disable_sync_subtasks (bool): Disable tasks to wait for sub tasks
            this is the default configuration. CAUTION do not enable this
            unless you must.

    Raises:
        celery.exceptions.TimeoutError: if ``timeout`` isn't
            :const:`None` and the operation takes longer than ``timeout``
            seconds.
    """
    if disable_sync_subtasks:
        assert_will_not_block()
    time_start = monotonic()
    remaining = None

    if on_message is not None:
        raise ImproperlyConfigured("Backend does not support on_message callback")

    results = []
    for result in self.results:
        remaining = None
        if timeout:
            remaining = timeout - (monotonic() - time_start)
            if remaining <= 0.0:
                raise TimeoutError("join operation timed out")
        value = result.get(
            timeout=remaining,
            propagate=propagate,
            interval=interval,
            no_ack=no_ack,
            on_interval=on_interval,
        )
        if callback:
            callback(result.id, value)
        else:
            results.append(value)
    return results


# Traceback (RuntimeError)
Traceback (most recent call last):
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/app/trace.py", line 385, in trace_task
R = retval = fun(*args, **kwargs)
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/app/trace.py", line 648, in __protected_call__
return self.run(*args, **kwargs)
File "/home/gsfish/work/netease/project/scan_detect/tasks.py", line 106, in test
return result_set.get(disable_sync_subtasks=False)
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/result.py", line 697, in get
on_interval=on_interval,
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/result.py", line 765, in join
interval=interval, no_ack=no_ack, on_interval=on_interval,
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/result.py", line 205, in get
assert_will_not_block()
File "/home/gsfish/.pyenv/versions/scan_detect/lib/python3.5/site-packages/celery/result.py", line 41, in assert_will_not_block
raise RuntimeError(E_WOULDBLOCK)
RuntimeError: Never call result.get() within a task!
See http://docs.celeryq.org/en/latest/userguide/tasks.html#task-synchronous-subtasks

# Fixed code
def join(
    self,
    timeout=None,
    propagate=True,
    interval=0.5,
    callback=None,
    no_ack=True,
    on_message=None,
    disable_sync_subtasks=True,
    on_interval=None,
):
    """Gather the results of all tasks as a list in order.

    Note:
        This can be an expensive operation for result store
        backends that must resort to polling (e.g., database).

        You should consider using :meth:`join_native` if your backend
        supports it.

    Warning:
        Waiting for tasks within a task may lead to deadlocks.
        Please see :ref:`task-synchronous-subtasks`.

    Arguments:
        timeout (float): The number of seconds to wait for results
            before the operation times out.
        propagate (bool): If any of the tasks raises an exception,
            the exception will be re-raised when this flag is set.
        interval (float): Time to wait (in seconds) before retrying to
            retrieve a result from the set.  Note that this does not have
            any effect when using the amqp result store backend,
            as it does not use polling.
        callback (Callable): Optional callback to be called for every
            result received.  Must have signature ``(task_id, value)``
            No results will be returned by this function if a callback
            is specified.  The order of results is also arbitrary when a
            callback is used.  To get access to the result object for
            a particular id you'll have to generate an index first:
            ``index = {r.id: r for r in gres.results.values()}``
            Or you can create new result objects on the fly:
            ``result = app.AsyncResult(task_id)`` (both will
            take advantage of the backend cache anyway).
        no_ack (bool): Automatic message acknowledgment (Note that if this
            is set to :const:`False` then the messages
            *will not be acknowledged*).
        disable_sync_subtasks (bool): Disable tasks to wait for sub tasks
            this is the default configuration. CAUTION do not enable this
            unless you must.

    Raises:
        celery.exceptions.TimeoutError: if ``timeout`` isn't
            :const:`None` and the operation takes longer than ``timeout``
            seconds.
    """
    if disable_sync_subtasks:
        assert_will_not_block()
    time_start = monotonic()
    remaining = None

    if on_message is not None:
        raise ImproperlyConfigured("Backend does not support on_message callback")

    results = []
    for result in self.results:
        remaining = None
        if timeout:
            remaining = timeout - (monotonic() - time_start)
            if remaining <= 0.0:
                raise TimeoutError("join operation timed out")
        value = result.get(
            timeout=remaining,
            propagate=propagate,
            interval=interval,
            no_ack=no_ack,
            on_interval=on_interval,
            disable_sync_subtasks=disable_sync_subtasks,
        )
        if callback:
            callback(result.id, value)
        else:
            results.append(value)
    return results