Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix context propagation in gRPC SerializingExecutor #4680

Merged
merged 2 commits into from
Feb 8, 2023

Conversation

richardstartin
Copy link
Member

@richardstartin richardstartin commented Feb 7, 2023

What Does This Do

SerializingExecutor is implemented as follows:

public final class SerializingExecutor implements Executor, Runnable {
...

  /**
   * Runs the given runnable strictly after all Runnables that were submitted
   * before it, and using the {@code executor} passed to the constructor.     .
   */
  @Override
  public void execute(Runnable r) {
    runQueue.add(checkNotNull(r, "'r' must not be null."));
    schedule(r);
  }

  private void schedule(@Nullable Runnable removable) {
    if (atomicHelper.runStateCompareAndSet(this, STOPPED, RUNNING)) {
      boolean success = false;
      try {
        executor.execute(this);
        success = true;
      } finally {
        // It is possible that at this point that there are still tasks in
        // the queue, it would be nice to keep trying but the error may not
        // be recoverable.  So we update our state and propagate so that if
        // our caller deems it recoverable we won't be stuck.
        if (!success) {
          if (removable != null) {
            // This case can only be reached if 'this' was not currently running, and we failed to
            // reschedule.  The item should still be in the queue for removal.
            // ConcurrentLinkedQueue claims that null elements are not allowed, but seems to not
            // throw if the item to remove is null.  If removable is present in the queue twice,
            // the wrong one may be removed.  It doesn't seem possible for this case to exist today.
            // This is important to run in case of RejectedExectuionException, so that future calls
            // to execute don't succeed and accidentally run a previous runnable.
            runQueue.remove(removable);
          }
          atomicHelper.runStateSet(this, STOPPED);
        }
      }
    }
  }

  @Override
  public void run() {
    Runnable r;
    try {
      Executor oldExecutor = executor;
      while (oldExecutor == executor && (r = runQueue.poll()) != null ) {
        try {
          r.run();
        } catch (RuntimeException e) {
          // Log it and keep going.
          log.log(Level.SEVERE, "Exception while executing runnable " + r, e);
        }
      }
    } finally {
      atomicHelper.runStateSet(this, STOPPED);
    }
    if (!runQueue.isEmpty()) {
      // we didn't enqueue anything but someone else did.
      schedule(null);
    }
  }
...

Currently, the active span is propagated when the SerializingExecutor is scheduled, and is active while all tasks are executed, instead of injecting the active span into the executed task.

The solution is simple:

  • Disable async propagation in SerializingExecutor#schedule so it doesn't get associated with the executor
  • Whitelist SerializingExecutor so it propagates the active span with the provided task

This allows a lot of scope management instrumentation to be removed, simplifying the instrumentation at the same time as ensuring the profiler is aware of all request/response activity.

Motivation

Additional Notes

@richardstartin richardstartin added type: bug inst: grpc gRPC instrumentation labels Feb 7, 2023
@richardstartin richardstartin requested a review from a team as a code owner February 7, 2023 19:13
@richardstartin richardstartin changed the title Rgs/grpc serializing executor Fix context propagation in gRPC SerializingExecutor Feb 7, 2023
@richardstartin richardstartin force-pushed the rgs/grpc-serializing-executor branch 2 times, most recently from 9750099 to c9e3bd9 Compare February 7, 2023 21:36
@richardstartin richardstartin force-pushed the rgs/grpc-serializing-executor branch from c9e3bd9 to 085171f Compare February 8, 2023 11:26
@richardstartin richardstartin merged commit cc1210e into master Feb 8, 2023
@richardstartin richardstartin deleted the rgs/grpc-serializing-executor branch February 8, 2023 13:58
@github-actions github-actions bot added this to the 1.8.0 milestone Feb 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inst: grpc gRPC instrumentation type: bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants