Skip to content

Commit 922755e

Browse files
experiment: Deadlock logger (#1198)
* experiment: Deadlock logger * fix: race issue with oauth refresh (#1199) * fix: race issue with oauth refresh * fix: review comment * fix: remove print * fix: deadlock in resource distributor (#1197) * adding dev-v11.2.1 tag to this commit to ensure building * fix: add deadlock logger * fix: changelog and build version * fix: only start deadlocklogger if it's enabled --------- Co-authored-by: Sattvik Chakravarthy <sattvik@supertokens.com> Co-authored-by: Supertokens Bot <>
1 parent 1be70ee commit 922755e

File tree

14 files changed

+265
-50
lines changed

14 files changed

+265
-50
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1010
## [11.3.0]
1111

1212
- Adds SAML features
13+
- Fixes potential deadlock issue with `TelemetryProvider`
14+
- Adds DeadlockLogger as an utility for discovering deadlock issues
1315

1416
### Migration
1517

@@ -68,6 +70,11 @@ CREATE INDEX IF NOT EXISTS saml_claims_app_id_tenant_id_index ON saml_claims (ap
6870
CREATE INDEX IF NOT EXISTS saml_claims_expires_at_index ON saml_claims (expires_at);
6971
```
7072

73+
## [11.2.1]
74+
75+
- Fixes deadlock issue with `ResourceDistributor`
76+
- Fixes race issues with Refreshing OAuth token
77+
7178
## [11.2.0]
7279

7380
- Adds opentelemetry-javaagent to the core distribution

cli/jar/cli.jar

0 Bytes
Binary file not shown.

config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ core_config_version: 0
187187
# will send telemetry data. This should be in the format http://<host>:<port> or https://<host>:<port>.
188188
# otel_collector_connection_uri:
189189

190+
# (OPTIONAL | Default: false) boolean value. Enables or disables the deadlock logger.
191+
# deadlock_logger_enable:
192+
190193
# (OPTIONAL | Default: null) string value. If specified, uses this URL as ACS URL for handling legacy SAML clients
191194
# saml_legacy_acs_url:
192195

devConfig.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ disable_telemetry: true
187187
# will send telemetry data. This should be in the format http://<host>:<port> or https://<host>:<port>.
188188
# otel_collector_connection_uri:
189189

190+
# (OPTIONAL | Default: false) boolean value. Enables or disables the deadlock logger.
191+
# deadlock_logger_enable:
192+
190193
# (OPTIONAL | Default: null) string value. If specified, uses this URL as ACS URL for handling legacy SAML clients
191194
saml_legacy_acs_url: "http://localhost:5225/api/oauth/saml"
192195

downloader/jar/downloader.jar

0 Bytes
Binary file not shown.

ee/jar/ee.jar

0 Bytes
Binary file not shown.
42.2 MB
Binary file not shown.

src/main/java/io/supertokens/Main.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.supertokens.cronjobs.cleanupOAuthSessionsAndChallenges.CleanupOAuthSessionsAndChallenges;
2525
import io.supertokens.cronjobs.deleteExpiredSAMLData.DeleteExpiredSAMLData;
2626
import io.supertokens.cronjobs.cleanupWebauthnExpiredData.CleanUpWebauthNExpiredDataCron;
27+
import io.supertokens.cronjobs.deadlocklogger.DeadlockLogger;
2728
import io.supertokens.cronjobs.deleteExpiredAccessTokenSigningKeys.DeleteExpiredAccessTokenSigningKeys;
2829
import io.supertokens.cronjobs.deleteExpiredDashboardSessions.DeleteExpiredDashboardSessions;
2930
import io.supertokens.cronjobs.deleteExpiredEmailVerificationTokens.DeleteExpiredEmailVerificationTokens;
@@ -283,6 +284,11 @@ private void init() throws IOException, StorageQueryException {
283284

284285
Cronjobs.addCronjob(this, CleanUpWebauthNExpiredDataCron.init(this, uniqueUserPoolIdsTenants));
285286

287+
// starts the DeadlockLogger if
288+
if (Config.getBaseConfig(this).isDeadlockLoggerEnabled()) {
289+
DeadlockLogger.getInstance().start();
290+
}
291+
286292
Cronjobs.addCronjob(this, DeleteExpiredSAMLData.init(this, uniqueUserPoolIdsTenants));
287293

288294
// this is to ensure tenantInfos are in sync for the new cron job as well

src/main/java/io/supertokens/ResourceDistributor.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ public static TenantIdentifier getAppForTesting() {
5151
return appUsedForTesting;
5252
}
5353

54-
public synchronized SingletonResource getResource(AppIdentifier appIdentifier, @Nonnull String key)
54+
public SingletonResource getResource(AppIdentifier appIdentifier, @Nonnull String key)
5555
throws TenantOrAppNotFoundException {
5656
return getResource(appIdentifier.getAsPublicTenantIdentifier(), key);
5757
}
5858

59-
public synchronized SingletonResource getResource(TenantIdentifier tenantIdentifier, @Nonnull String key)
59+
public SingletonResource getResource(TenantIdentifier tenantIdentifier, @Nonnull String key)
6060
throws TenantOrAppNotFoundException {
6161
// first we do exact match
6262
SingletonResource resource = resources.get(new KeyClass(tenantIdentifier, key));
@@ -70,14 +70,6 @@ public synchronized SingletonResource getResource(TenantIdentifier tenantIdentif
7070
throw new TenantOrAppNotFoundException(tenantIdentifier);
7171
}
7272

73-
MultitenancyHelper.getInstance(main).refreshTenantsInCoreBasedOnChangesInCoreConfigOrIfTenantListChanged(true);
74-
75-
// we try again..
76-
resource = resources.get(new KeyClass(tenantIdentifier, key));
77-
if (resource != null) {
78-
return resource;
79-
}
80-
8173
// then we see if the user has configured anything to do with connectionUriDomain, and if they have,
8274
// then we must return null cause the user has not specifically added tenantId to it
8375
for (KeyClass currKey : resources.keySet()) {
@@ -101,11 +93,11 @@ public synchronized SingletonResource getResource(TenantIdentifier tenantIdentif
10193
}
10294

10395
@TestOnly
104-
public synchronized SingletonResource getResource(@Nonnull String key) {
96+
public SingletonResource getResource(@Nonnull String key) {
10597
return resources.get(new KeyClass(appUsedForTesting, key));
10698
}
10799

108-
public synchronized SingletonResource setResource(TenantIdentifier tenantIdentifier,
100+
public SingletonResource setResource(TenantIdentifier tenantIdentifier,
109101
@Nonnull String key,
110102
SingletonResource resource) {
111103
SingletonResource alreadyExists = resources.get(new KeyClass(tenantIdentifier, key));
@@ -116,7 +108,7 @@ public synchronized SingletonResource setResource(TenantIdentifier tenantIdentif
116108
return resource;
117109
}
118110

119-
public synchronized SingletonResource removeResource(TenantIdentifier tenantIdentifier,
111+
public SingletonResource removeResource(TenantIdentifier tenantIdentifier,
120112
@Nonnull String key) {
121113
SingletonResource singletonResource = resources.get(new KeyClass(tenantIdentifier, key));
122114
if (singletonResource == null) {
@@ -126,18 +118,18 @@ public synchronized SingletonResource removeResource(TenantIdentifier tenantIden
126118
return singletonResource;
127119
}
128120

129-
public synchronized SingletonResource setResource(AppIdentifier appIdentifier,
121+
public SingletonResource setResource(AppIdentifier appIdentifier,
130122
@Nonnull String key,
131123
SingletonResource resource) {
132124
return setResource(appIdentifier.getAsPublicTenantIdentifier(), key, resource);
133125
}
134126

135-
public synchronized SingletonResource removeResource(AppIdentifier appIdentifier,
127+
public SingletonResource removeResource(AppIdentifier appIdentifier,
136128
@Nonnull String key) {
137129
return removeResource(appIdentifier.getAsPublicTenantIdentifier(), key);
138130
}
139131

140-
public synchronized void clearAllResourcesWithResourceKey(String inputKey) {
132+
public void clearAllResourcesWithResourceKey(String inputKey) {
141133
List<KeyClass> toRemove = new ArrayList<>();
142134
resources.forEach((key, value) -> {
143135
if (key.key.equals(inputKey)) {
@@ -149,7 +141,7 @@ public synchronized void clearAllResourcesWithResourceKey(String inputKey) {
149141
}
150142
}
151143

152-
public synchronized Map<KeyClass, SingletonResource> getAllResourcesWithResourceKey(String inputKey) {
144+
public Map<KeyClass, SingletonResource> getAllResourcesWithResourceKey(String inputKey) {
153145
Map<KeyClass, SingletonResource> result = new HashMap<>();
154146
resources.forEach((key, value) -> {
155147
if (key.key.equals(inputKey)) {
@@ -160,7 +152,7 @@ public synchronized Map<KeyClass, SingletonResource> getAllResourcesWithResource
160152
}
161153

162154
@TestOnly
163-
public synchronized SingletonResource setResource(@Nonnull String key,
155+
public SingletonResource setResource(@Nonnull String key,
164156
SingletonResource resource) {
165157
return setResource(appUsedForTesting, key, resource);
166158
}

src/main/java/io/supertokens/config/CoreConfig.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ public class CoreConfig {
426426
"null)")
427427
private String otel_collector_connection_uri = null;
428428

429+
@EnvName("DEADLOCK_LOGGER_ENABLE")
430+
@ConfigYamlOnly
431+
@JsonProperty
432+
@ConfigDescription(
433+
"Enables or disables the deadlock logger. (Default: false)")
434+
private boolean deadlock_logger_enable = false;
435+
429436
@IgnoreForAnnotationCheck
430437
private static boolean disableOAuthValidationForTest = false;
431438

@@ -681,6 +688,10 @@ public String getOtelCollectorConnectionURI() {
681688
return otel_collector_connection_uri;
682689
}
683690

691+
public boolean isDeadlockLoggerEnabled() {
692+
return deadlock_logger_enable;
693+
}
694+
684695
public String getSAMLLegacyACSURL() {
685696
return saml_legacy_acs_url;
686697
}

0 commit comments

Comments
 (0)