|  | @@ -111,6 +111,21 @@ class BaseBackend(object):
 | 
											
												
													
														|  |          return self.store_result(task_id, exc, status=states.FAILURE,
 |  |          return self.store_result(task_id, exc, status=states.FAILURE,
 | 
											
												
													
														|  |                                   traceback=traceback, request=request)
 |  |                                   traceback=traceback, request=request)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    def chord_error_from_stack(self, callback, exc=None):
 | 
											
												
													
														|  | 
 |  | +        from celery import group
 | 
											
												
													
														|  | 
 |  | +        app = self.app
 | 
											
												
													
														|  | 
 |  | +        backend = app._tasks[callback.task].backend
 | 
											
												
													
														|  | 
 |  | +        try:
 | 
											
												
													
														|  | 
 |  | +            group(
 | 
											
												
													
														|  | 
 |  | +                [app.signature(errback)
 | 
											
												
													
														|  | 
 |  | +                 for errback in callback.options.get('link_error') or []],
 | 
											
												
													
														|  | 
 |  | +                app=app,
 | 
											
												
													
														|  | 
 |  | +            ).apply_async((callback.id, ))
 | 
											
												
													
														|  | 
 |  | +        except Exception as eb_exc:
 | 
											
												
													
														|  | 
 |  | +            return backend.fail_from_current_stack(callback.id, exc=eb_exc)
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            return backend.fail_from_current_stack(callback.id, exc=exc)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      def fail_from_current_stack(self, task_id, exc=None):
 |  |      def fail_from_current_stack(self, task_id, exc=None):
 | 
											
												
													
														|  |          type_, real_exc, tb = sys.exc_info()
 |  |          type_, real_exc, tb = sys.exc_info()
 | 
											
												
													
														|  |          try:
 |  |          try:
 | 
											
										
											
												
													
														|  | @@ -502,21 +517,18 @@ class KeyValueStoreBackend(BaseBackend):
 | 
											
												
													
														|  |              deps = GroupResult.restore(gid, backend=task.backend)
 |  |              deps = GroupResult.restore(gid, backend=task.backend)
 | 
											
												
													
														|  |          except Exception as exc:
 |  |          except Exception as exc:
 | 
											
												
													
														|  |              callback = maybe_signature(task.request.chord, app=self.app)
 |  |              callback = maybe_signature(task.request.chord, app=self.app)
 | 
											
												
													
														|  | -            return app._tasks[callback.task].backend.fail_from_current_stack(
 |  | 
 | 
											
												
													
														|  | -                callback.id,
 |  | 
 | 
											
												
													
														|  | -                exc=ChordError('Cannot restore group: {0!r}'.format(exc)),
 |  | 
 | 
											
												
													
														|  | 
 |  | +            return self.chord_error_from_stack(
 | 
											
												
													
														|  | 
 |  | +                callback,
 | 
											
												
													
														|  | 
 |  | +                ChordError('Cannot restore group: {0!r}'.format(exc)),
 | 
											
												
													
														|  |              )
 |  |              )
 | 
											
												
													
														|  |          if deps is None:
 |  |          if deps is None:
 | 
											
												
													
														|  |              try:
 |  |              try:
 | 
											
												
													
														|  |                  raise ValueError(gid)
 |  |                  raise ValueError(gid)
 | 
											
												
													
														|  |              except ValueError as exc:
 |  |              except ValueError as exc:
 | 
											
												
													
														|  |                  callback = maybe_signature(task.request.chord, app=self.app)
 |  |                  callback = maybe_signature(task.request.chord, app=self.app)
 | 
											
												
													
														|  | -                task = app._tasks[callback.task]
 |  | 
 | 
											
												
													
														|  | -                return task.backend.fail_from_current_stack(
 |  | 
 | 
											
												
													
														|  | -                    callback.id,
 |  | 
 | 
											
												
													
														|  | -                    exc=ChordError('GroupResult {0} no longer exists'.format(
 |  | 
 | 
											
												
													
														|  | -                        gid,
 |  | 
 | 
											
												
													
														|  | -                    ))
 |  | 
 | 
											
												
													
														|  | 
 |  | +                return self.chord_error_from_stack(
 | 
											
												
													
														|  | 
 |  | +                    callback,
 | 
											
												
													
														|  | 
 |  | +                    ChordError('GroupResult {0} no longer exists'.format(gid)),
 | 
											
												
													
														|  |                  )
 |  |                  )
 | 
											
												
													
														|  |          val = self.incr(key)
 |  |          val = self.incr(key)
 | 
											
												
													
														|  |          if val >= len(deps):
 |  |          if val >= len(deps):
 | 
											
										
											
												
													
														|  | @@ -534,16 +546,14 @@ class KeyValueStoreBackend(BaseBackend):
 | 
											
												
													
														|  |                  except StopIteration:
 |  |                  except StopIteration:
 | 
											
												
													
														|  |                      reason = repr(exc)
 |  |                      reason = repr(exc)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                app._tasks[callback.task].backend.fail_from_current_stack(
 |  | 
 | 
											
												
													
														|  | -                    callback.id, exc=ChordError(reason),
 |  | 
 | 
											
												
													
														|  | -                )
 |  | 
 | 
											
												
													
														|  | 
 |  | +                self.chord_error_from_stack(callback, ChordError(reason))
 | 
											
												
													
														|  |              else:
 |  |              else:
 | 
											
												
													
														|  |                  try:
 |  |                  try:
 | 
											
												
													
														|  |                      callback.delay(ret)
 |  |                      callback.delay(ret)
 | 
											
												
													
														|  |                  except Exception as exc:
 |  |                  except Exception as exc:
 | 
											
												
													
														|  | -                    app._tasks[callback.task].backend.fail_from_current_stack(
 |  | 
 | 
											
												
													
														|  | -                        callback.id,
 |  | 
 | 
											
												
													
														|  | -                        exc=ChordError('Callback error: {0!r}'.format(exc)),
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    self.chord_error_from_stack(
 | 
											
												
													
														|  | 
 |  | +                        callback,
 | 
											
												
													
														|  | 
 |  | +                        ChordError('Callback error: {0!r}'.format(exc)),
 | 
											
												
													
														|  |                      )
 |  |                      )
 | 
											
												
													
														|  |              finally:
 |  |              finally:
 | 
											
												
													
														|  |                  deps.delete()
 |  |                  deps.delete()
 |