fix SLF4J-469

This commit is contained in:
Ceki Gulcu 2019-12-16 21:52:14 +01:00
parent ca93154c79
commit c6c7a98a7e
5 changed files with 208 additions and 10 deletions

View File

@ -56,7 +56,12 @@
<pathelement location="../slf4j-simple/target/slf4j-simple-${currentVersion}.jar" />
</path >
<path id="pathNoBinding">
<pathelement location="target/test-classes/" />
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
</path >
<path id="incompatibleMultiBinding">
<pathelement location="target/test-classes/" />
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
@ -102,11 +107,12 @@
</target>
<target name="testAll" depends="init,
testMissingSingletonMethod,
testMissingSingletonMethod,
testMismatch,
testMatch,
testMultiBinding,
testIncompatibleMultiBinding,
testNoBinding,
testMatch,
testMultiBinding,
testIncompatibleMultiBinding,
testFuture_16Series,
testActiveSecurityManager">
</target>
@ -215,7 +221,17 @@
</junit>
</target>
<target name="testNoBinding">
<junit printsummary="yes" fork="no" haltonfailure="yes">
<classpath refid="pathNoBinding" />
<formatter type="plain" />
<test fork="yes" todir="target/unit-reports"
outfile="TEST-NOBINDING"
name="org.slf4j.helpers.NoBindingMultithreadedInitializationTest2" />
</junit>
</target>
<condition property="runFromWithinIntegrationModule">
<contains string="${user.dir}" substring="integration" />

View File

@ -0,0 +1,65 @@
/**
* Copyright (c) 2004-2016 QOS.ch
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.helpers;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggerAccessingThread2 extends Thread {
private static int LOOP_LEN = 64;
final CyclicBarrier barrier;
final int count;
final AtomicLong eventCount;
List<Logger> loggerList;
public LoggerAccessingThread2(final CyclicBarrier barrier, List<Logger> loggerList, final int count, final AtomicLong eventCount) {
this.barrier = barrier;
this.loggerList = loggerList;
this.count = count;
this.eventCount = eventCount;
}
public void run() {
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
String loggerNamePrefix = this.getClass().getName();
for (int i = 0; i < LOOP_LEN; i++) {
Logger logger = LoggerFactory.getLogger(loggerNamePrefix + "-" + count + "-" + i);
loggerList.add(logger);
Thread.yield();
logger.info("in run method");
eventCount.getAndIncrement();
}
}
}

View File

@ -0,0 +1,112 @@
/**
* Copyright (c) 2004-2016 QOS.ch
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.helpers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.EventRecodingLogger;
import junit.framework.TestCase;
public class NoBindingMultithreadedInitializationTest2 extends TestCase {
final protected static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
protected final AtomicLong eventCount = new AtomicLong(0);
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
int diff = new Random().nextInt(10000);
public NoBindingMultithreadedInitializationTest2(String name) {
super(name);
}
public void testNoBindingMultiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
@SuppressWarnings("unused")
LoggerAccessingThread2[] accessors = harness();
Logger logger = LoggerFactory.getLogger(getClass().getName());
logger.info("hello");
eventCount.getAndIncrement();
assertAllSubstLoggersAreFixed();
long recordedEventCount = getRecordedEventCount();
int LENIENCY_COUNT = 16;
long expectedEventCount = eventCount.get() + extraLogEvents();
assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT,
expectedEventCount < recordedEventCount + LENIENCY_COUNT);
}
protected int extraLogEvents() {
return 0;
}
private void assertAllSubstLoggersAreFixed() {
for (Logger logger : createdLoggers) {
if (logger instanceof SubstituteLogger) {
SubstituteLogger substLogger = (SubstituteLogger) logger;
if (substLogger.delegate() instanceof EventRecodingLogger)
fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger");
}
}
}
private LoggerAccessingThread2[] harness() throws InterruptedException, BrokenBarrierException {
LoggerAccessingThread2[] threads = new LoggerAccessingThread2[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new LoggerAccessingThread2(barrier, createdLoggers, i, eventCount);
threads[i].start();
}
// trigger barrier
barrier.await();
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i].join();
}
return threads;
}
final String loggerName = this.getClass().getName();
protected long getRecordedEventCount() {
return eventCount.get();
}
}

View File

@ -150,10 +150,6 @@ public final class LoggerFactory {
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
} catch (NoClassDefFoundError ncde) {
String msg = ncde.getMessage();
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
@ -177,9 +173,18 @@ public final class LoggerFactory {
} catch (Exception e) {
failedBinding(e);
throw new IllegalStateException("Unexpected initialization failure", e);
} finally {
postBindCleanUp();
}
}
private static void postBindCleanUp() {
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
}
private static void fixSubstituteLoggers() {
synchronized (SUBST_FACTORY) {
SUBST_FACTORY.postInitialization();

View File

@ -22,7 +22,7 @@ abstract public class MultithreadedInitializationTest {
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
final private AtomicLong eventCount = new AtomicLong(0);
protected final AtomicLong eventCount = new AtomicLong(0);
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
int diff = new Random().nextInt(10000);