Skip to content

Commit b507297

Browse files
committed
Fixed race condition occurring in case MDC class is initialized while org.slf4j.LoggerFactory is initializing logback-classic's LoggerContext.
Signed-off-by: Ceki Gulcu <[email protected]>
1 parent f5b3bc5 commit b507297

File tree

5 files changed

+73
-31
lines changed

5 files changed

+73
-31
lines changed

logback-classic/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@
269269
--add-modules jakarta.mail
270270
--add-modules jakarta.servlet
271271
--add-opens ch.qos.logback.core/ch.qos.logback.core.testUtil=java.naming
272+
--add-opens ch.qos.logback.classic/ch.qos.logback.classic.issue.github450=ch.qos.logback.core
272273
--add-opens ch.qos.logback.classic/ch.qos.logback.classic.testUtil=ch.qos.logback.core
273274
--add-opens ch.qos.logback.classic/ch.qos.logback.classic.jsonTest=ALL-UNNAMED
274275
</argLine>
@@ -288,6 +289,7 @@
288289
<exclude>org.slf4j.implTest.InitializationOutputTest.java</exclude>
289290
<exclude>ch.qos.logback.classic.util.ContextInitializerTest.java</exclude>
290291
<exclude>ch.qos.logback.classic.spi.InvocationTest.java</exclude>
292+
<exclude>ch.qos.logback.classic.issue.github450.SLF4JIssue450Test</exclude>
291293
</excludes>
292294
</configuration>
293295
</execution>
@@ -300,11 +302,15 @@
300302
<configuration>
301303
<forkCount>4</forkCount>
302304
<reuseForks>false</reuseForks>
305+
<argLine>
306+
--add-opens ch.qos.logback.classic/ch.qos.logback.classic.issue.github450=ch.qos.logback.core
307+
</argLine>
303308
<includes>
304309
<include>org.slf4j.implTest.MultithreadedInitializationTest.java</include>
305310
<include>org.slf4j.implTest.InitializationOutputTest.java</include>
306311
<include>ch.qos.logback.classic.util.ContextInitializerTest.java</include>
307312
<include>ch.qos.logback.classic.spi.InvocationTest.java</include>
313+
<include>ch.qos.logback.classic.issue.github450.SLF4JIssue450Test</include>
308314
</includes>
309315
</configuration>
310316
</execution>

logback-classic/src/main/java/ch/qos/logback/classic/spi/LogbackServiceProvider.java

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,23 @@ public class LogbackServiceProvider implements SLF4JServiceProvider {
2626
// to avoid constant folding by the compiler, this field must *not* be final
2727
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
2828

29-
private LoggerContext defaultLoggerContext;
30-
private IMarkerFactory markerFactory;
31-
private LogbackMDCAdapter mdcAdapter;
32-
// private final ContextSelectorStaticBinder contextSelectorBinder =
33-
// ContextSelectorStaticBinder.getSingleton();
34-
// private static Object KEY = new Object();
35-
// private volatile boolean initialized = false;
29+
private LoggerContext defaultLoggerContext = new LoggerContext();
30+
31+
32+
// org.slf4j.LoggerFactory expects providers to initialize markerFactory as early as possible.
33+
private IMarkerFactory markerFactory = new BasicMarkerFactory();
34+
35+
// org.slf4j.LoggerFactory expects providers to initialize their MDCAdapter field
36+
// as early as possible, preferably at construction time.
37+
private LogbackMDCAdapter mdcAdapter = new LogbackMDCAdapter();
3638

3739
@Override
3840
public void initialize() {
39-
defaultLoggerContext = new LoggerContext();
4041
defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME);
41-
initializeLoggerContext();
42-
defaultLoggerContext.start();
43-
markerFactory = new BasicMarkerFactory();
44-
mdcAdapter = new LogbackMDCAdapter();
4542
// set the MDCAdapter for the defaultLoggerContext immediately
4643
defaultLoggerContext.setMDCAdapter(mdcAdapter);
44+
initializeLoggerContext();
45+
defaultLoggerContext.start();
4746
}
4847

4948
private void initializeLoggerContext() {
@@ -68,15 +67,6 @@ private void initializeLoggerContext() {
6867

6968
public ILoggerFactory getLoggerFactory() {
7069
return defaultLoggerContext;
71-
72-
// if (!initialized) {
73-
// return defaultLoggerContext;
74-
//
75-
//
76-
// if (contextSelectorBinder.getContextSelector() == null) {
77-
// throw new IllegalStateException("contextSelector cannot be null. See also " + NULL_CS_URL);
78-
// }
79-
// return contextSelectorBinder.getContextSelector().getLoggerContext();
8070
}
8171

8272
@Override
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!DOCTYPE configuration>
3+
<!--
4+
~ Logback: the reliable, generic, fast and flexible logging framework.
5+
~ Copyright (C) 1999-2025, QOS.ch. All rights reserved.
6+
~
7+
~ This program and the accompanying materials are dual-licensed under
8+
~ either the terms of the Eclipse Public License v1.0 as published by
9+
~ the Eclipse Foundation
10+
~
11+
~ or (per the licensee's choosing)
12+
~
13+
~ under the terms of the GNU Lesser General Public License version 2.1
14+
~ as published by the Free Software Foundation.
15+
-->
16+
17+
18+
<configuration>
19+
<import class="ch.qos.logback.classic.issue.github450.Issues450LoggerContextListener"/>
20+
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
21+
<import class="ch.qos.logback.core.ConsoleAppender"/>
22+
<import class="ch.qos.logback.core.read.ListAppender"/>
23+
24+
<contextListener class="Issues450LoggerContextListener"/>
25+
26+
<appender name="LIST" class="ListAppender"/>
27+
28+
<appender name="CONSOLE" class="ConsoleAppender">
29+
<encoder class="PatternLayoutEncoder">
30+
<pattern>%d{HH:mm:ss.SSS} [%t] **[%X]** %-5level %logger{36} - %msg%n</pattern>
31+
</encoder>
32+
</appender>
33+
34+
<logger name="app" level="debug" additivity="false">
35+
<appender-ref ref="CONSOLE"/>
36+
</logger>
37+
38+
<root level="debug">
39+
<appender-ref ref="LIST"/>
40+
<appender-ref ref="CONSOLE"/>
41+
</root>
42+
</configuration>

logback-classic/src/test/java/ch/qos/logback/classic/issue/github450/SLF4JIssue450Test.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,24 @@
1616

1717
import ch.qos.logback.classic.ClassicConstants;
1818
import ch.qos.logback.classic.ClassicTestConstants;
19-
import ch.qos.logback.classic.spi.ILoggingEvent;
2019
import ch.qos.logback.classic.spi.LoggingEvent;
2120
import ch.qos.logback.core.CoreConstants;
2221
import ch.qos.logback.core.read.ListAppender;
22+
import org.junit.jupiter.api.Test;
2323
import org.slf4j.Logger;
2424
import org.slf4j.LoggerFactory;
25-
import org.slf4j.MDC;
2625

27-
public class Main {
26+
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.junit.jupiter.api.Assertions.assertNotNull;
2828

29-
public static void main(String[] args) {
30-
System.setProperty(ClassicConstants.CONFIG_FILE_PROPERTY, "logback-classic/"+ClassicTestConstants.INPUT_PREFIX + "issue/gh_issues_450.xml");
29+
public class SLF4JIssue450Test {
30+
31+
32+
@Test
33+
public void smoke() {
34+
System.setProperty(ClassicConstants.CONFIG_FILE_PROPERTY, ClassicTestConstants.INPUT_PREFIX + "issue/gh_issues_450.xml");
3135
System.setProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY, "stdout");
32-
Logger logger = LoggerFactory.getLogger(Main.class);
36+
Logger logger = LoggerFactory.getLogger(SLF4JIssue450Test.class);
3337
logger.info("toto");
3438
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
3539

@@ -38,8 +42,8 @@ public static void main(String[] args) {
3842
LoggingEvent le0 = (LoggingEvent) listAppender.list.get(0);
3943

4044
String val = le0.getMDCPropertyMap().get("issues450");
41-
if(val == null) {
42-
throw new RuntimeException("issues450 missing property: issues450");
43-
}
45+
assertNotNull(val);
46+
assertEquals("12", val);
47+
4448
}
4549
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
<!-- slf4j.version property is used below, in
7575
logback-classic/pom.xml, /logback-examples/src/main/resources/setClasspath.cmd, download.html
7676
-->
77-
<slf4j.version>2.0.16</slf4j.version>
77+
<slf4j.version>2.0.17-SNAPSHOT</slf4j.version>
7878
<cal10n.version>0.8.1</cal10n.version>
7979
<consolePlugin.version>1.1.0</consolePlugin.version>
8080
<jackson.version>2.15.0</jackson.version>

0 commit comments

Comments
 (0)