You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Todor Boev (Jira)" <ji...@apache.org> on 2020/09/24 09:35:00 UTC

[jira] [Updated] (LOG4J2-2934) Under OSGi log4j-api almost never binds to a Provider (e.g. log4j-core)

     [ https://issues.apache.org/jira/browse/LOG4J2-2934?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Todor Boev updated LOG4J2-2934:
-------------------------------
    Description: 
The log4j-api is has a BundleActivator that has to obtain a lock provided by ProviderUtil so that it can block the binding of a Provider until one becomes available by another bundle.

At the same time when the first class load request hits LogManager it runs a static code block that ultimately calls ProviderUtil to get a Provider by also obtaining the lock first. Except in this case if a provider is not available the lock is released and SimpleLoginContextFactory is used.

There is a race condition between these execution flows. If the BundleActivator manages to get the lock first the correct Provider will be used with it's LoginContextFactory.
If the thread that triggers a class load of LogManager manages to grab the lock first the SimpleLoginContextFactory will be used.

There is no predictable way to reorder this execution it is sufficient for any arbitrary bundle to load a class that has a static Logger field before log4j-api is started to break the Provider binding. In almost all cases the wrong Provider is bound. Basically this part of the OSGi integration of Log4j 2 has to be completely bypassed using various hacks to actually the non-OSGi way to bind a Provider to work.

The correct way to fix this is for ProviderUtil to check whether it runs under OSGi and if so to always block waiting for a Provider to be supplied. Such a check can be done trivially usually in a static block by attempting to class load via reflection some class from the core OSGi API.

> Under OSGi log4j-api almost never binds to a Provider (e.g. log4j-core)
> -----------------------------------------------------------------------
>
>                 Key: LOG4J2-2934
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-2934
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: API
>            Reporter: Todor Boev
>            Priority: Major
>
> The log4j-api is has a BundleActivator that has to obtain a lock provided by ProviderUtil so that it can block the binding of a Provider until one becomes available by another bundle.
> At the same time when the first class load request hits LogManager it runs a static code block that ultimately calls ProviderUtil to get a Provider by also obtaining the lock first. Except in this case if a provider is not available the lock is released and SimpleLoginContextFactory is used.
> There is a race condition between these execution flows. If the BundleActivator manages to get the lock first the correct Provider will be used with it's LoginContextFactory.
> If the thread that triggers a class load of LogManager manages to grab the lock first the SimpleLoginContextFactory will be used.
> There is no predictable way to reorder this execution it is sufficient for any arbitrary bundle to load a class that has a static Logger field before log4j-api is started to break the Provider binding. In almost all cases the wrong Provider is bound. Basically this part of the OSGi integration of Log4j 2 has to be completely bypassed using various hacks to actually the non-OSGi way to bind a Provider to work.
> The correct way to fix this is for ProviderUtil to check whether it runs under OSGi and if so to always block waiting for a Provider to be supplied. Such a check can be done trivially usually in a static block by attempting to class load via reflection some class from the core OSGi API.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)