apm-agent-go: [apmgrpc] Call other service methods in goroutine, prompting error: context canceled

Describe the bug In the A method, the B method is called by the goroutine, and rpc error occurs: code = Canceled desc = context canceled

Code

...
func (k *Server) Get(ctx context.Context, r *pb.Request) (*pb.Response, error) {
	go func() {
		resp, err := CallBServerMethod(ctx)
		if err != nil {
			log.Println(err)
		}
	}()
        ... 
}

To Reproduce Steps to reproduce the behavior:

  1. 2 gRPC Servers, A and B.
  2. The RPC method in A Server, call the RPC method of B Server via goroutine (pass ctx for link tracking)
  3. The RPC method call of A Server ends, and the RPC method of B Server returned by goroutine returns an error.
  4. See error: rpc error: code = Canceled desc = context canceled

Expected behavior Call is normal, link tracking is normal.

There is a problem here. If ctx is not passed, the link tracking is incomplete. However, if ctx is passed, an error will occur in the scene called by goroutine.

What should I do?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (10 by maintainers)

Most upvoted comments

Excellent, thanks for testing.

@axw Ok, understand the situation. Because we are using it in a production environment, it is generally safer to use a released version.

I will try the master branch in the local environment later.

@EDDYCJY #478 is merged, so you can try the fix if you update to the master branch.

I’ve also just created a new PR, https://github.com/elastic/apm-agent-go/pull/481, which introduces a top-level function apm.DetachedContext. You can use this to create a context which propagates trace context, but will not be cancelled if the enclosing context is cancelled or its deadline is reached.

So instead of

newctx := context.Background()
if tx := apm.TransactionFromContext(ctx); tx != nil {
    newctx = apm.ContextWithTransaction(newctx, tx)
}
if span := apm.SpanFromContext(ctx); span != nil {
    newctx = apm.ContextWithSpan(newctx, span)
}

you would write

newctx := apm.DetachedContext(ctx)

I would appreciate your feedback on this.