Closed ppkarwasz closed 2 years ago
PRs without a related issue tend to fall in between the cracks. I have created a jira issue for this PR SLF4J-568
@ceki, I believe this PR addresses the concerns of the open Jira issue SLF4J-548.
@ppkarwasz Indeed, thank you.
@ceki Could you check this, please? We have issues to adopt SLF4J 2 in WildFly-Core downstream. The service load based on TCCL is a mess. @ppkarwasz solution solved it for log4j2 API service load of the corresponding impl. It would be great to get minor release for it.
@boris-unckel Do you have a description of the problem you are facing? Or a reference to the original problem?
From a cursory look, Piotr's patch 1) invokes AccessController.doPrivileged if a SecurityManager is present 2) catches instantiations problems of found services.
Am I missing anything?
You mention TCCL but the code in question does not use TCCL (on purpose).
@ceki,
The patch also calls ServiceLoader.load
with a classloader parameter (the classloader that loaded SLF4J), so it doesn't use the TCCL. ServiceLoader.load(Class)
uses the TCCL.
It's basically a simplified version of ServiceLoaderUtil in log4j-api
, which is used by other Log4j2 modules, so it has to deal with caller sensitivity problems. ServiceLoaderUtil
also deals with OSGI directly, whereas SLF4J requires a Service Loader Mediator (Apache Aries) to be present in the OSGI container.
Hello @ceki ,
steps to reproduce:
General: setup latest Maven and a Java 11 environment
1) clone and build https://github.com/boris-unckel/slf4j-jboss-logmanager/tree/JBLOGGING-165_upgrade_slf4j2 with
mvn clean install
2) git clone https://github.com/wildfly/wildfly-core.git
2a) optional run to proove everything is OK with WF-Core before:
mvn clean install -Dsecurity.manager -DallTests -Dmaven.test.failure.ignore=true >../buildlog.txt 2>&1
3) upgrade pom.xml line 246 (version.org.jboss.slf4j.slf4j-jboss-logmanager) to 1.2.1.Final-SNAPSHOT ( https://github.com/wildfly/wildfly-core/blob/main/pom.xml#L246 )
4) upgrade pom.xml line 256 (version.org.slf4j) to 2.0.2 ( https://github.com/wildfly/wildfly-core/blob/main/pom.xml#L256 )
5) upgrade testsuite/embedded/pom.xml line (version.ch.qos.logback) to 1.4.1 ( https://github.com/wildfly/wildfly-core/blob/main/testsuite/embedded/pom.xml#L41 )
5) mvn clean install -Dsecurity.manager -DallTests -Dmaven.test.failure.ignore=true >../buildlog.txt 2>&1
The issues occur without SecurityManager, too. To check simply remove -Dsecurity.manager
.
I thought I could develop a workaround, initializing slf4j early in the log subsystem: https://github.com/boris-unckel/wildfly-core/tree/upgrade_slf4j2_showcase but it fails for the embedded server edition and breaks existing usecases. The second downside is the increase of dependencies and length of startup.
Kind regards Boris
@boris-unckel Thanks for the information. I am quite swamped at the moment. I'll deal with this when I can, but it make take a few days.
@ceki Hope you're fine. Any updates on this one?
@ceki Hope you're fine. Any updates on this one?
Hi @boris-unckel, I am sorry for not having attended to this PR. It is at the top of my SLF4J todo list. I expect to start working on SLF4J on the week of Monday 14th and there should be a new release before the end of November.
If you wish things to go a little faster, there is also the option of championing a release.
@boris-unckel Can you please check if release 2.0.4 solves the issue for you?
Here is a quote from the release notes:
LoggerFactory
now uses the class loader that loadedLoggerFactory
class itself to find providers of typeSLF4JServiceProvider
. Previously, the thread context class loader was used. This was unintentional and the current behavior more closely matches that of the SLF4J 1.7 series and earlier. This tentatively fixes SLF4J-544 as well as several other related/duplicating issues.
Hello @ceki @ppkarwasz
I have tested it with WildFly-Core and 2.0.4 still has issues. I have ported the ServiceLoaderUtil from Log4j2 and it works immediately. This is the showcase[1]: https://github.com/boris-unckel/slf4j/tree/serviceloader
The WildFly-Core integrated version of it is here: https://github.com/boris-unckel/wildfly-core/tree/upgrade_slf4j2_showcase2
[1] The showcase contains copies of code from log4j2. The commit message shows source URLs.
@boris-unckel Can you please clarify whether slf4j-api version 1.7.x works for WildFly-Core?
@boris-unckel,
Thanks for the tests. I was pretty sure this patch is equivalent to what we did in Log4j2 (minus the MethodHandles
stuff that Log4j2 needs because the caller of ServiceLoaderUtil
and the class itself can be in different JPMS modules). I'll look into it this weekend.
Given the amount of debugging that ServiceLoaderUtil
has seen (and a couple of bug reports :-) ), I think that including it into SLF4J would be the safest and easiest solution.
Full disclosure: there is still an open Log4j2 bug report (cf. LOG4J2-3624) that might be related to ServiceLoaderUtil
, but I was unable to reproduce it.
@ceki @ppkarwasz thanks for your fast reply
@boris-unckel Can you please clarify whether slf4j-api version 1.7.x works for WildFly-Core?
Yes, sure: It's used in the current production version https://github.com/wildfly/wildfly-core/blob/19.0.0.Final/pom.xml#L257 you can download it here: https://www.wildfly.org/downloads/
It's also a implicit module: https://docs.wildfly.org/27/Developer_Guide.html#how-and-when-is-an-implicit-module-dependency-added
@boris-unckel Slf4j's LoggerFactory in both version 1.7.x and version 2.0.4 (but not 2.0.3) use the same class loader, i.e. the class loader that loaded the LoggerFactory class to look for the logging implementation. Thus, why would 1.7.36 work in a given context, in this case WildFly, and 2.0.4 fail in the same context?
Running the tests under "wildfly-core/testsuite/embedded" with SLF4J 2.0.4, more specifically the test LogbackStandaloneTestCase.testLogback, I observe the following exception:
Caused by: org.wildfly.core.embedded.EmbeddedProcessStartException: WFLYEMB0021: Cannot start embedded process
at org.wildfly.embedded@20.0.0.Beta3-SNAPSHOT//org.wildfly.core.embedded.EmbeddedStandaloneServerFactory$StandaloneServerImpl.start(EmbeddedStandaloneServerFactory.java:324)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.wildfly.core.embedded.EmbeddedManagedProcessImpl.invokeOnServer(EmbeddedManagedProcessImpl.java:107)
... 47 more
Caused by: java.util.concurrent.ExecutionException: JBTHR00005: Operation failed
at org.jboss.threads.AsyncFutureTask.get(AsyncFutureTask.java:253)
at org.wildfly.embedded@20.0.0.Beta3-SNAPSHOT//org.wildfly.core.embedded.EmbeddedStandaloneServerFactory$StandaloneServerImpl.start(EmbeddedStandaloneServerFactory.java:305)
... 50 more
Caused by: java.lang.Exception: WFLYSRV0056: Server boot has failed in an unrecoverable manner; exiting. See previous messages for details. - Server configuration file in use: standalone.xml
at org.jboss.as.server@20.0.0.Beta3-SNAPSHOT//org.jboss.as.server.BootstrapListener.bootFailure(BootstrapListener.java:87)
at org.jboss.as.server@20.0.0.Beta3-SNAPSHOT//org.jboss.as.server.ServerService.boot(ServerService.java:440)
at org.jboss.as.controller@20.0.0.Beta3-SNAPSHOT//org.jboss.as.controller.AbstractControllerService$1.run(AbstractControllerService.java:473)
at java.base/java.lang.Thread.run(Thread.java:1589)
I also observe that SLF4J provider finds logback and can create logger instances apparently with no problems. As for the actual cause of the failure, that remains a mystery.
Update: setting pom entries to use slf4j 2.0.4 and logback 1.4.5, the following commands complete successfully.
git clone https://github.com/wildfly/wildfly-core.git
cd wildcore-core
mvn clean
mvn install -Dmaven.test.skip=true
cd testsuite/embedded/
mvn install
Here are the edits on the project:
diff --git a/pom.xml b/pom.xml
index c514d93798..9f3bab98e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -241,7 +241,7 @@
<version.org.jboss.remoting>5.0.26.Final</version.org.jboss.remoting>
<version.org.jboss.remotingjmx.remoting-jmx>3.0.4.Final</version.org.jboss.remotingjmx.remoting-jmx>
<version.org.jboss.shrinkwrap.shrinkwrap>1.2.6</version.org.jboss.shrinkwrap.shrinkwrap>
- <version.org.jboss.slf4j.slf4j-jboss-logmanager>1.1.0.Final</version.org.jboss.slf4j.slf4j-jboss-logmanager>
+ <version.org.jboss.slf4j.slf4j-jboss-logmanager>1.2.1.Final-SNAPSHOT</version.org.jboss.slf4j.slf4j-jboss-logmanager>
<version.org.jboss.staxmapper>1.3.0.Final</version.org.jboss.staxmapper>
<version.org.jboss.stdio>1.1.0.Final</version.org.jboss.stdio>
<version.org.jboss.threads>2.4.0.Final</version.org.jboss.threads>
@@ -251,7 +251,7 @@
<version.org.jmockit>1.39</version.org.jmockit>
<version.org.mockito>3.10.0</version.org.mockito>
<version.org.projectodd.vdx>1.1.6</version.org.projectodd.vdx>
- <version.org.slf4j>1.7.36</version.org.slf4j>
+ <version.org.slf4j>2.0.4</version.org.slf4j>
<version.org.syslog4j>0.9.30</version.org.syslog4j>
<version.org.wildfly.client.config>1.0.1.Final</version.org.wildfly.client.config>
<version.org.wildfly.common>1.6.0.Final</version.org.wildfly.common>
diff --git a/testsuite/embedded/pom.xml b/testsuite/embedded/pom.xml
index 244db51955..79f6f0ae94 100644
--- a/testsuite/embedded/pom.xml
+++ b/testsuite/embedded/pom.xml
@@ -38,7 +38,7 @@
<jbossas.ts.dir>${jbossas.ts.integ.dir}/..</jbossas.ts.dir>
<jbossas.project.dir>${jbossas.ts.dir}</jbossas.project.dir>
<wildfly.home>${project.basedir}/target/wildfly-core</wildfly.home>
- <version.ch.qos.logback>1.2.9</version.ch.qos.logback>
+ <version.ch.qos.logback>1.4.5</version.ch.qos.logback>
</properties>
<dependencies>
@ceki Thanks for checking it. Please don't -Dmaven.test.skip=true
but mvn clean install -Dsecurity.manager -DallTests -Dmaven.test.failure.ignore=true >../buildlog.txt 2>&1
The logging subsystem has tests, there are integration tests and some tests are embedded and CLI client relevant, where logging is needed.
It's late today, I'm posting a gist with the result tomorrow, hopefully morning.
@boris-unckel I have rerun the tests a second time without the security manager.
I am seeing Slf4jLoggingProfilesTestCase.testProfiles
failing. The strange part is that it looks like Slf4jServiceActivator
is not being called at all.
@boris-unckel Slf4j's LoggerFactory in both version 1.7.x and version 2.0.4 (but not 2.0.3) use the same class loader, i.e. the class loader that loaded the LoggerFactory class to look for the logging implementation. Thus, why would 1.7.36 work in a given context, in this case WildFly, and 2.0.4 fail in the same context?
@ceki Good morning, including the SecurityManager (why do you run without?) it seems down to last one error. It's not about the classloader, you're correct for this part.
* [ERROR] Failures:
* [ERROR] Slf4jLoggingProfilesTestCase.testDeploymentConfigurationResource:29->AbstractLoggingProfilesTestCase.testDeploymentConfigurationResource:301->AbstractLoggingProfilesTe* stCase.deploy:321->AbstractLoggingProfilesTestCase.deploy:332->AbstractLoggingTestCase.deploy:210 Failed to deploy logging1.jar: 10 assets: {"WFLYCTL0080: Failed services" => {"* jboss.deployment.unit.\"logging1.jar\".INSTALL" => "WFLYSRV0153: Failed to process phase INSTALL of deployment \"logging1.jar\"
Caused by: java.util.ServiceConfigurationError: org.jboss.msc.service.ServiceActivator: Provider org.jboss.as.test.integration.logging.profiles.Slf4jServiceActivator could n ot be instantiated
Caused by: java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also https://www.slf4j.org/codes.html#unsucce ssfulInit"}}
* [ERROR] Slf4jLoggingProfilesTestCase.testProfiles:29->AbstractLoggingProfilesTestCase.testProfiles:202->AbstractLoggingProfilesTestCase.deploy:321->AbstractLoggingProfilesTest* Case.deploy:332->AbstractLoggingTestCase.deploy:210 Failed to deploy logging1.jar: 10 assets: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"logging1.jar\".INSTALL* " => "WFLYSRV0153: Failed to process phase INSTALL of deployment \"logging1.jar\"
Caused by: java.util.ServiceConfigurationError: org.jboss.msc.service.ServiceActivator: Provider org.jboss.as.test.integration.logging.profiles.Slf4jServiceActivator could n ot be instantiated
Caused by: java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: Unexpected initialization failure
Caused by: java.security.AccessControlException: WFSM000001: Permission check failed (permission \"(\"java.io.FilePermission\" \"/home/borisunckel/.m2/repository/org/jboss/s lf4j/slf4j-jboss-logmanager/1.2.1.Final-SNAPSHOT/slf4j-jboss-logmanager-1.2.1.Final-SNAPSHOT.jar\" \"read\")\" in code source \"(vfs:/content/logging1.jar <no signer certificate s>)\" of \"ModuleClassLoader for Module \"deployment.logging1.jar\" from Service Module Loader\")"}}
and I assume it fails due to this change, removing the privileged action: https://github.com/qos-ch/slf4j/commit/43a36303e5a2338c22ec9aad5b01a401034eb553#diff-204f23f1c787a5f1f6162f79eae7d8694d723ef7788e23b79ed270a15c677b00L108-L111
I am seeing Slf4jLoggingProfilesTestCase.testProfiles failing. The strange part is that it looks like Slf4jServiceActivator is not being called at all.
My guess is <version.org.jboss.slf4j.slf4j-jboss-logmanager>1.2.1.Final-SNAPSHOT
is Maven central/JBoss public rep based, correct? And the following PR is missing, I have tested with a locally built version: https://github.com/jboss-logging/slf4j-jboss-logmanager/pull/16
Some background information regarding the Security Manager, modules and PriviligedAction use: https://docs.wildfly.org/27/WildFly_Elytron_Security.html#Elytron_JSM_Further_Background
The version of slf4j-jboss-logmanager I am using is from https://github.com/boris-unckel/slf4j-jboss-logmanager/
The git log
command yields the following output:
Author: boris-unckel <bu.githubcom@mail.unckel.net>
Date: Fri Sep 23 17:56:20 2022 +0200
[JBLOGGING-165] Upgrade slf4j 2.0.4
Fixes https://issues.redhat.com/browse/JBLOGGING-165
[cut]
So it looks like I am using the same version of slf4j-jboss-logmanager.
@ceki I have tested mvn clean install -DallTests -Dsecurity.manager -Dmaven.test.failure.ignore=true >../2022-11-23_2131.txt 2>&1
leading to the error described above: https://github.com/qos-ch/slf4j/pull/304#issuecomment-1325990974
and mvn clean install -DallTests -Dmaven.test.failure.ignore=true >../2022-11-24_1647.txt 2>&1
which runs without any error. Please turn back to the original patch https://github.com/qos-ch/slf4j/pull/304/commits/06d6c81cbcbe4a8d3844cccd09d471f95029a987
@boris-unckel Sorry for not having been clearer earlier. I rather not change the class loading behavior of org.slf4j.LoggerFactory
without very solid justification.
Given Apache (Jakarta) Commnons-Logging experience, SLF4J was created in 2005 chiefly to avoid class loading problems during logging. It does so by adopting the simplest class loading model possible. Patch 06d6c81c offers a more dynamic model, and from your previous comments, which is apparently not even needed.
As for using SecurityManager
that is a different question and I am open to that.
@boris-unckel Sorry for not having been clearer earlier. I rather not change the class loading behavior of
org.slf4j.LoggerFactory
without very solid justification.
@ceki, the following code does not change the class loading behavior: since the action
lambda was created by LoggerFactory
, running action
is equivalent to calling the function directly. The SecurityManager
part is required by WildFly, because the code that initiates SLF4J is not privileged enough to access Logback, while slf4j-api
is.
final ClassLoader cl = LoggerFactory.class.getClassLoader();
final PrivilegedAction<ServiceLoader<SLF4JServiceProvider>> action = () -> ServiceLoader.load(SLF4JServiceProvider.class, cl);
final ServiceLoader<SLF4JServiceProvider> serviceLoader = System.getSecurityManager() != null
? AccessController.doPrivileged(action)
: action.run();
I am far from being an expert on SecurityManager
, but I believe that Boris known what he is doing.
@ceki Yes, sure. It was meant only regarding the Security Manager, the ClassLoading works as the tests have shown. @ppkarwasz thanks for the snipplet
Cool. We are all in agreement then.
@ceki Just to be sure: You're preparing the fix? Or do you expect a PR?
I am preparing a fix.
Thanks to you both for all your support.
@boris-unckel Can you please verify that 3bc58f3e81cf committed a few moments ago works as expected?
@ceki Thanks, I have prepared a local snapshot build and the test is running right now. I'm going to give a status with the result tomorrow morning.
@ceki The test run completed successfully. Thanks for your ongoing support to get this solved.
Thanks for making the SLF4J API embeddable in a jar archive...
If both the servlet container and a web application use SLF4J,
ServiceLoader
calls are susceptible to three problems:SLF4JProviderService
),LoggerFactory
fails if called by unprivileged code.This PR should solve these problems.