On Sun, 2 Mar 2025 03:16:02 GMT, Jason Mehrens <d...@openjdk.org> wrote:

>> I'd have to disagree with the points you make.
>> 
>> The fact is that loggers are never expected to modify the passed parameters. 
>> To ask people to "disown" the parameters they pass to a logger requires that 
>> your best advice on how to write a log statement with mutable values must 
>> look something like:
>> 
>> 
>>   if (logger.isEnabled(level)) {
>>     // Avoid copying parameters when logging is disabled.
>>     var arg1Copy = arg1.defensiveCopy();
>>     var arg2Copy = arg2.defensiveCopy();
>>     logger.log(level, "foo={0}, bar={1}", arg1Copy, arg2Copy);
>>   }
>> 
>> 
>> as opposed to:
>> 
>> 
>>     logger.log(level, "foo={0}, bar={1}", arg1, arg2);
>> 
>> 
>> The former is, in my opinion, a pretty awful user experience, error prone, 
>> and (more to the point) something that almost nobody ever does in real code 
>> because, reasonably, they trust the internal logger classes not to be 
>> malicious.
>> 
>> The comment about the record being owned by the logger means that it can't 
>> be cached and reused, or passed to different log statements etc. It doesn't 
>> give logging classes any freedom to modify the log statement parameters.
>> 
>> The other issue with "defer processing to another thread", even if you do 
>> format in the original thread, is that either:
>> 
>> 1. You format just the arguments to strings -- Now things like `{0,date}` 
>> are broken because you turned date/time arguments into strings what are no 
>> longer formattable with the original format string.
>> 2. You format the entire message -- Now any handlers downstream cannot use 
>> the format message (the thing with the placeholders in) as a key to identify 
>> the log statements, which is sometimes really important for analysis.
>> 
>> It's just really hard (maybe impossible) to create any general solution 
>> where a log record (as opposed to some custom semi-flattened form) can be 
>> safely used between threads without this being visible in some way to users.
>> 
>> So my (personal) strong advice for Handler implementations is:
>> 1. Never let the log record you are given escape the call to `publish()`.
>> 2. You can store metadata from the log record "on the side", but only for 
>> non user-supplied arguments.
>> 
>> So, if you wanted to use something like `MemoryHandler`, subclass it and 
>> override `publish()` to make new log records to pass into its queue, which 
>> contain only flat formatted information (and even then you might break 
>> assumptions of a downstream handler).
>> 
>> However, if you are formatting everything in the `publish()` method, you 
>> don't reall...
>
>>The former is, in my opinion, a pretty awful user experience...
> 
> Specifically, I'm referring to this, with awareness of the above described 
> limitations:
> 
> //String.format is var-arg
> logger.log(Level.SEVERE, () -> { return String.format("foo=%s bar=%s", arg1, 
> arg2); });
> 
> //logger is not var-arg     
> if (logger.isLoggable(lvl)) { //if arg1 and arg2 known to be never null
>     logger.log(lvl, "foo={0} bar={1}", new Object[]{arg1.toString(), 
> arg2.toString()});
> }
>          
> //logger is not var-arg
> if (logger.isLoggable(lvl)) { //if arg1 and arg2 are nullable
>     logger.log(lvl, "foo={0} bar={1}", new Object[]{Objects.toString(arg1), 
> Objects.toString(arg2)});
> }
> 
> 
> How did you worked around this deadlock issue prior to this patch?  That 
> would be awesome information to add to the JIRA ticket for those that would 
> like this patch but are unable to upgrade.

The only workaround is to early format parameters, either at the call site or 
in the logger/handler.
This bug has been around for a very long time, and I suspect that it hasn't 
been a serious issue for people because, in general, most toString() 
implementations are non-locking and most log statements are disabled most of 
the time. It's also a probabilistic deadlock which requires some instance to be 
being accessed by two threads concurrently. I have however witnessed it causing 
issues in real production systems.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/23491#discussion_r1977228065

Reply via email to