Skip to content

Commit 597747d

Browse files
authored
Add ThreadContextPermission for markAsSystemContext and allow core to perform the method (opensearch-project#15016)
* Add RuntimePermission for markAsSystemContext and allow core to perform the method Signed-off-by: Craig Perkins <cwperx@amazon.com> * private Signed-off-by: Craig Perkins <cwperx@amazon.com> * Surround with doPrivileged Signed-off-by: Craig Perkins <cwperx@amazon.com> * Create ThreadContextAccess Signed-off-by: Craig Perkins <cwperx@amazon.com> * Create notion of ThreadContextPermission Signed-off-by: Craig Perkins <cwperx@amazon.com> * Add to CHANGELOG Signed-off-by: Craig Perkins <cwperx@amazon.com> * Add javadoc Signed-off-by: Craig Perkins <cwperx@amazon.com> * Add to test-framework.policy file Signed-off-by: Craig Perkins <cwperx@amazon.com> * Mark as internal Signed-off-by: Craig Perkins <cwperx@amazon.com> --------- Signed-off-by: Craig Perkins <cwperx@amazon.com>
1 parent 5c19809 commit 597747d

File tree

19 files changed

+128
-16
lines changed

19 files changed

+128
-16
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
99
- [Workload Management] Add queryGroupId to Task ([14708](https://github.com/opensearch-project/OpenSearch/pull/14708))
1010
- Add setting to ignore throttling nodes for allocation of unassigned primaries in remote restore ([#14991](https://github.com/opensearch-project/OpenSearch/pull/14991))
1111
- Add basic aggregation support for derived fields ([#14618](https://github.com/opensearch-project/OpenSearch/pull/14618))
12+
- Add ThreadContextPermission for markAsSystemContext and allow core to perform the method ([#15016](https://github.com/opensearch-project/OpenSearch/pull/15016))
1213

1314
### Dependencies
1415
- Bump `org.apache.commons:commons-lang3` from 3.14.0 to 3.15.0 ([#14861](https://github.com/opensearch-project/OpenSearch/pull/14861))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.secure_sm;
10+
11+
import java.security.BasicPermission;
12+
13+
/**
14+
* Permission to utilize methods in the ThreadContext class that are normally not accessible
15+
*
16+
* @see ThreadGroup
17+
* @see SecureSM
18+
*/
19+
public final class ThreadContextPermission extends BasicPermission {
20+
21+
/**
22+
* Creates a new ThreadContextPermission object.
23+
*
24+
* @param name target name
25+
*/
26+
public ThreadContextPermission(String name) {
27+
super(name);
28+
}
29+
30+
/**
31+
* Creates a new ThreadContextPermission object.
32+
* This constructor exists for use by the {@code Policy} object to instantiate new Permission objects.
33+
*
34+
* @param name target name
35+
* @param actions ignored
36+
*/
37+
public ThreadContextPermission(String name, String actions) {
38+
super(name, actions);
39+
}
40+
}

server/src/main/java/org/opensearch/cluster/service/ClusterApplierService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.opensearch.common.util.concurrent.OpenSearchExecutors;
6262
import org.opensearch.common.util.concurrent.PrioritizedOpenSearchThreadPoolExecutor;
6363
import org.opensearch.common.util.concurrent.ThreadContext;
64+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
6465
import org.opensearch.core.concurrency.OpenSearchRejectedExecutionException;
6566
import org.opensearch.telemetry.metrics.noop.NoopMetricsRegistry;
6667
import org.opensearch.telemetry.metrics.tags.Tags;
@@ -396,7 +397,7 @@ private void submitStateUpdateTask(
396397
final ThreadContext threadContext = threadPool.getThreadContext();
397398
final Supplier<ThreadContext.StoredContext> supplier = threadContext.newRestorableContext(true);
398399
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
399-
threadContext.markAsSystemContext();
400+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
400401
final UpdateTask updateTask = new UpdateTask(
401402
config.priority(),
402403
source,

server/src/main/java/org/opensearch/cluster/service/MasterService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.opensearch.common.util.concurrent.OpenSearchExecutors;
6767
import org.opensearch.common.util.concurrent.PrioritizedOpenSearchThreadPoolExecutor;
6868
import org.opensearch.common.util.concurrent.ThreadContext;
69+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
6970
import org.opensearch.core.Assertions;
7071
import org.opensearch.core.common.text.Text;
7172
import org.opensearch.core.concurrency.OpenSearchRejectedExecutionException;
@@ -1022,7 +1023,7 @@ public <T> void submitStateUpdateTasks(
10221023
final ThreadContext threadContext = threadPool.getThreadContext();
10231024
final Supplier<ThreadContext.StoredContext> supplier = threadContext.newRestorableContext(true);
10241025
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
1025-
threadContext.markAsSystemContext();
1026+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
10261027

10271028
List<Batcher.UpdateTask> safeTasks = tasks.entrySet()
10281029
.stream()

server/src/main/java/org/opensearch/common/util/concurrent/ThreadContext.java

+17
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@
4545
import org.opensearch.core.common.io.stream.StreamOutput;
4646
import org.opensearch.core.common.io.stream.Writeable;
4747
import org.opensearch.http.HttpTransportSettings;
48+
import org.opensearch.secure_sm.ThreadContextPermission;
4849
import org.opensearch.tasks.Task;
4950
import org.opensearch.tasks.TaskThreadContextStatePropagator;
5051

5152
import java.io.IOException;
5253
import java.nio.charset.StandardCharsets;
54+
import java.security.Permission;
5355
import java.util.ArrayList;
5456
import java.util.Collection;
5557
import java.util.Collections;
@@ -111,6 +113,10 @@ public final class ThreadContext implements Writeable {
111113
*/
112114
public static final String ACTION_ORIGIN_TRANSIENT_NAME = "action.origin";
113115

116+
// thread context permissions
117+
118+
private static final Permission ACCESS_SYSTEM_THREAD_CONTEXT_PERMISSION = new ThreadContextPermission("markAsSystemContext");
119+
114120
private static final Logger logger = LogManager.getLogger(ThreadContext.class);
115121
private static final ThreadContextStruct DEFAULT_CONTEXT = new ThreadContextStruct();
116122
private final Map<String, String> defaultHeader;
@@ -554,8 +560,19 @@ boolean isDefaultContext() {
554560
/**
555561
* Marks this thread context as an internal system context. This signals that actions in this context are issued
556562
* by the system itself rather than by a user action.
563+
*
564+
* Usage of markAsSystemContext is guarded by a ThreadContextPermission. In order to use
565+
* markAsSystemContext, the codebase needs to explicitly be granted permission in the JSM policy file.
566+
*
567+
* Add an entry in the grant portion of the policy file like this:
568+
*
569+
* permission org.opensearch.secure_sm.ThreadContextPermission "markAsSystemContext";
557570
*/
558571
public void markAsSystemContext() {
572+
SecurityManager sm = System.getSecurityManager();
573+
if (sm != null) {
574+
sm.checkPermission(ACCESS_SYSTEM_THREAD_CONTEXT_PERMISSION);
575+
}
559576
threadLocal.set(threadLocal.get().setSystemContext(propagators));
560577
}
561578

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.common.util.concurrent;
10+
11+
import org.opensearch.SpecialPermission;
12+
import org.opensearch.common.annotation.InternalApi;
13+
14+
import java.security.AccessController;
15+
import java.security.PrivilegedAction;
16+
17+
/**
18+
* This class wraps the {@link ThreadContext} operations requiring access in
19+
* {@link AccessController#doPrivileged(PrivilegedAction)} blocks.
20+
*
21+
* @opensearch.internal
22+
*/
23+
@SuppressWarnings("removal")
24+
@InternalApi
25+
public final class ThreadContextAccess {
26+
27+
private ThreadContextAccess() {}
28+
29+
public static <T> T doPrivileged(PrivilegedAction<T> operation) {
30+
SpecialPermission.check();
31+
return AccessController.doPrivileged(operation);
32+
}
33+
34+
public static void doPrivilegedVoid(Runnable action) {
35+
SpecialPermission.check();
36+
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
37+
action.run();
38+
return null;
39+
});
40+
}
41+
}

server/src/main/java/org/opensearch/index/seqno/GlobalCheckpointSyncAction.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.opensearch.common.inject.Inject;
4545
import org.opensearch.common.settings.Settings;
4646
import org.opensearch.common.util.concurrent.ThreadContext;
47+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
4748
import org.opensearch.core.action.ActionListener;
4849
import org.opensearch.core.common.io.stream.StreamInput;
4950
import org.opensearch.core.index.shard.ShardId;
@@ -98,7 +99,7 @@ public GlobalCheckpointSyncAction(
9899
public void updateGlobalCheckpointForShard(final ShardId shardId) {
99100
final ThreadContext threadContext = threadPool.getThreadContext();
100101
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
101-
threadContext.markAsSystemContext();
102+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
102103
execute(new Request(shardId), ActionListener.wrap(r -> {}, e -> {
103104
if (ExceptionsHelper.unwrap(e, AlreadyClosedException.class, IndexShardClosedException.class) == null) {
104105
logger.info(new ParameterizedMessage("{} global checkpoint sync failed", shardId), e);

server/src/main/java/org/opensearch/index/seqno/RetentionLeaseBackgroundSyncAction.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.opensearch.common.inject.Inject;
4949
import org.opensearch.common.settings.Settings;
5050
import org.opensearch.common.util.concurrent.ThreadContext;
51+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
5152
import org.opensearch.core.action.ActionListener;
5253
import org.opensearch.core.common.io.stream.StreamInput;
5354
import org.opensearch.core.common.io.stream.StreamOutput;
@@ -122,7 +123,7 @@ final void backgroundSync(ShardId shardId, String primaryAllocationId, long prim
122123
final ThreadContext threadContext = threadPool.getThreadContext();
123124
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
124125
// we have to execute under the system context so that if security is enabled the sync is authorized
125-
threadContext.markAsSystemContext();
126+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
126127
final Request request = new Request(shardId, retentionLeases);
127128
final ReplicationTask task = (ReplicationTask) taskManager.register("transport", "retention_lease_background_sync", request);
128129
transportService.sendChildRequest(

server/src/main/java/org/opensearch/index/seqno/RetentionLeaseSyncAction.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.opensearch.common.inject.Inject;
5151
import org.opensearch.common.settings.Settings;
5252
import org.opensearch.common.util.concurrent.ThreadContext;
53+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
5354
import org.opensearch.core.action.ActionListener;
5455
import org.opensearch.core.common.io.stream.StreamInput;
5556
import org.opensearch.core.common.io.stream.StreamOutput;
@@ -137,7 +138,7 @@ final void sync(
137138
final ThreadContext threadContext = threadPool.getThreadContext();
138139
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
139140
// we have to execute under the system context so that if security is enabled the sync is authorized
140-
threadContext.markAsSystemContext();
141+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
141142
final Request request = new Request(shardId, retentionLeases);
142143
final ReplicationTask task = (ReplicationTask) taskManager.register("transport", "retention_lease_sync", request);
143144
transportService.sendChildRequest(

server/src/main/java/org/opensearch/indices/replication/checkpoint/PublishCheckpointAction.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.opensearch.common.inject.Inject;
2525
import org.opensearch.common.settings.Settings;
2626
import org.opensearch.common.util.concurrent.ThreadContext;
27+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
2728
import org.opensearch.core.action.ActionListener;
2829
import org.opensearch.core.common.io.stream.StreamInput;
2930
import org.opensearch.index.IndexNotFoundException;
@@ -113,7 +114,7 @@ final void publish(IndexShard indexShard, ReplicationCheckpoint checkpoint) {
113114
final ThreadContext threadContext = threadPool.getThreadContext();
114115
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
115116
// we have to execute under the system context so that if security is enabled the sync is authorized
116-
threadContext.markAsSystemContext();
117+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
117118
PublishCheckpointRequest request = new PublishCheckpointRequest(checkpoint);
118119
final ReplicationTask task = (ReplicationTask) taskManager.register("transport", "segrep_publish_checkpoint", request);
119120
final ReplicationTimer timer = new ReplicationTimer();

server/src/main/java/org/opensearch/transport/RemoteClusterConnection.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.opensearch.common.settings.Settings;
4141
import org.opensearch.common.unit.TimeValue;
4242
import org.opensearch.common.util.concurrent.ThreadContext;
43+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
4344
import org.opensearch.common.util.io.IOUtils;
4445
import org.opensearch.core.action.ActionListener;
4546
import org.opensearch.core.common.io.stream.StreamInput;
@@ -136,7 +137,7 @@ void collectNodes(ActionListener<Function<String, DiscoveryNode>> listener) {
136137
new ContextPreservingActionListener<>(threadContext.newRestorableContext(false), listener);
137138
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
138139
// we stash any context here since this is an internal execution and should not leak any existing context information
139-
threadContext.markAsSystemContext();
140+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
140141

141142
final ClusterStateRequest request = new ClusterStateRequest();
142143
request.clear();

server/src/main/java/org/opensearch/transport/SniffConnectionStrategy.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.opensearch.common.settings.Setting;
4848
import org.opensearch.common.settings.Settings;
4949
import org.opensearch.common.util.concurrent.ThreadContext;
50+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
5051
import org.opensearch.common.util.io.IOUtils;
5152
import org.opensearch.core.action.ActionListener;
5253
import org.opensearch.core.common.Strings;
@@ -349,7 +350,7 @@ private void collectRemoteNodes(Iterator<Supplier<DiscoveryNode>> seedNodes, Act
349350
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
350351
// we stash any context here since this is an internal execution and should not leak any
351352
// existing context information.
352-
threadContext.markAsSystemContext();
353+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
353354
transportService.sendRequest(
354355
connection,
355356
ClusterStateAction.NAME,

server/src/main/resources/org/opensearch/bootstrap/security.policy

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ grant codeBase "${codebase.opensearch}" {
4848
permission java.lang.RuntimePermission "setContextClassLoader";
4949
// needed for SPI class loading
5050
permission java.lang.RuntimePermission "accessDeclaredMembers";
51+
permission org.opensearch.secure_sm.ThreadContextPermission "markAsSystemContext";
5152
};
5253

5354
//// Very special jar permissions:

server/src/main/resources/org/opensearch/bootstrap/test-framework.policy

+1
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,5 @@ grant {
157157
permission java.lang.RuntimePermission "reflectionFactoryAccess";
158158
permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
159159
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
160+
permission org.opensearch.secure_sm.ThreadContextPermission "markAsSystemContext";
160161
};

server/src/test/java/org/opensearch/cluster/metadata/TemplateUpgradeServiceTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.opensearch.cluster.service.ClusterService;
4848
import org.opensearch.common.collect.Tuple;
4949
import org.opensearch.common.util.concurrent.ThreadContext;
50+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
5051
import org.opensearch.core.action.ActionListener;
5152
import org.opensearch.core.common.bytes.BytesArray;
5253
import org.opensearch.core.common.bytes.BytesReference;
@@ -225,7 +226,7 @@ public void testUpdateTemplates() {
225226
service.upgradesInProgress.set(additionsCount + deletionsCount + 2); // +2 to skip tryFinishUpgrade
226227
final ThreadContext threadContext = threadPool.getThreadContext();
227228
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
228-
threadContext.markAsSystemContext();
229+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
229230
service.upgradeTemplates(additions, deletions);
230231
}
231232

server/src/test/java/org/opensearch/common/util/concurrent/ThreadContextTests.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ public void testPreservesThreadsOriginalContextOnRunException() throws IOExcepti
565565
threadContext.putHeader("foo", "bar");
566566
boolean systemContext = randomBoolean();
567567
if (systemContext) {
568-
threadContext.markAsSystemContext();
568+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
569569
}
570570
threadContext.putTransient("foo", "bar_transient");
571571
withContext = threadContext.preserveContext(new AbstractRunnable() {
@@ -736,7 +736,7 @@ public void testMarkAsSystemContext() throws IOException {
736736
assertFalse(threadContext.isSystemContext());
737737
try (ThreadContext.StoredContext context = threadContext.stashContext()) {
738738
assertFalse(threadContext.isSystemContext());
739-
threadContext.markAsSystemContext();
739+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
740740
assertTrue(threadContext.isSystemContext());
741741
}
742742
assertFalse(threadContext.isSystemContext());
@@ -761,7 +761,7 @@ public void testSystemContextWithPropagator() {
761761
assertEquals(Integer.valueOf(1), threadContext.getTransient("test_transient_propagation_key"));
762762
assertEquals("bar", threadContext.getHeader("foo"));
763763
try (ThreadContext.StoredContext ctx = threadContext.stashContext()) {
764-
threadContext.markAsSystemContext();
764+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
765765
assertNull(threadContext.getHeader("foo"));
766766
assertNull(threadContext.getTransient("test_transient_propagation_key"));
767767
assertEquals("1", threadContext.getHeader("default"));
@@ -793,7 +793,7 @@ public void testSerializeSystemContext() throws IOException {
793793
threadContext.writeTo(out);
794794
try (ThreadContext.StoredContext ctx = threadContext.stashContext()) {
795795
assertEquals("test", threadContext.getTransient("test_transient_propagation_key"));
796-
threadContext.markAsSystemContext();
796+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
797797
threadContext.writeTo(outFromSystemContext);
798798
assertNull(threadContext.getHeader("foo"));
799799
assertNull(threadContext.getTransient("test_transient_propagation_key"));

server/src/test/java/org/opensearch/telemetry/tracing/ThreadContextBasedTracerContextStorageTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.opensearch.common.settings.Settings;
1313
import org.opensearch.common.util.concurrent.ThreadContext;
1414
import org.opensearch.common.util.concurrent.ThreadContext.StoredContext;
15+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
1516
import org.opensearch.telemetry.Telemetry;
1617
import org.opensearch.telemetry.TelemetrySettings;
1718
import org.opensearch.telemetry.metrics.MetricsTelemetry;
@@ -260,7 +261,7 @@ public void testSpanNotPropagatedToChildSystemThreadContext() {
260261
try (StoredContext ignored = threadContext.stashContext()) {
261262
assertThat(threadContext.getTransient(ThreadContextBasedTracerContextStorage.CURRENT_SPAN), is(not(nullValue())));
262263
assertThat(threadContextStorage.get(ThreadContextBasedTracerContextStorage.CURRENT_SPAN), is(span));
263-
threadContext.markAsSystemContext();
264+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
264265
assertThat(threadContext.getTransient(ThreadContextBasedTracerContextStorage.CURRENT_SPAN), is(nullValue()));
265266
}
266267
}

server/src/test/resources/org/opensearch/bootstrap/test.policy

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
grant {
10-
// allow to test Security policy and codebases
10+
// allow to test Security policy and codebases
1111
permission java.util.PropertyPermission "*", "read,write";
1212
permission java.security.SecurityPermission "createPolicy.JavaPolicy";
1313
};

test/framework/src/main/java/org/opensearch/cluster/service/FakeThreadPoolClusterManagerService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.opensearch.common.util.concurrent.OpenSearchExecutors;
4545
import org.opensearch.common.util.concurrent.PrioritizedOpenSearchThreadPoolExecutor;
4646
import org.opensearch.common.util.concurrent.ThreadContext;
47+
import org.opensearch.common.util.concurrent.ThreadContextAccess;
4748
import org.opensearch.core.action.ActionListener;
4849
import org.opensearch.node.Node;
4950
import org.opensearch.telemetry.metrics.noop.NoopMetricsRegistry;
@@ -134,7 +135,7 @@ public void run() {
134135
scheduledNextTask = false;
135136
final ThreadContext threadContext = threadPool.getThreadContext();
136137
try (ThreadContext.StoredContext ignored = threadContext.stashContext()) {
137-
threadContext.markAsSystemContext();
138+
ThreadContextAccess.doPrivilegedVoid(threadContext::markAsSystemContext);
138139
task.run();
139140
}
140141
if (waitForPublish == false) {

0 commit comments

Comments
 (0)