Merge pull request #11306 from jetty/fix/jetty-12/11282/debug-deadlock

Fixes #11282 - Deadlocks with DEBUG logging enabled in jetty-server testing.
This commit is contained in:
Joakim Erdfelt 2024-01-25 09:26:49 -06:00 committed by GitHub
commit ef75595e8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 16 deletions

View File

@ -492,13 +492,14 @@ public class ByteArrayEndPoint extends AbstractEndPoint
public String toString()
{
int q;
ByteBuffer b;
Object b;
String o;
try (AutoLock lock = _lock.lock())
try (AutoLock lock = _lock.tryLock())
{
q = _inQ.size();
b = _inQ.peek();
o = BufferUtil.toDetailString(_out);
boolean held = lock.isHeldByCurrentThread();
q = held ? _inQ.size() : -1;
b = held ? _inQ.peek() : "?";
o = held ? BufferUtil.toDetailString(_out) : "?";
}
return String.format("%s[q=%d,q[0]=%s,o=%s]", super.toString(), q, b, o);
}

View File

@ -546,16 +546,18 @@ public class HttpChannelState implements HttpChannel, Components
@Override
public String toString()
{
try (AutoLock ignored = _lock.lock())
try (AutoLock lock = _lock.tryLock())
{
return String.format("%s@%x{handling=%s, handled=%b, send=%s, completed=%b, request=%s}",
boolean held = lock.isHeldByCurrentThread();
return String.format("%s@%x{handling=%s, handled=%s, send=%s, completed=%s, request=%s}",
this.getClass().getSimpleName(),
hashCode(),
_handling,
_handled,
_streamSendState,
_callbackCompleted,
_request);
held ? _handling : "?",
held ? _handled : "?",
held ? _streamSendState : "?",
held ? _callbackCompleted : "?",
held ? _request : "?"
);
}
}
@ -1270,6 +1272,7 @@ public class HttpChannelState implements HttpChannel, Components
* <p>
* The implementation maintains the {@link #_streamSendState} before taking
* and serializing the call to the {@link #_writeCallback}, which was set by the call to {@code write}.
*
* @param x The reason for the failure.
*/
@Override
@ -1498,6 +1501,7 @@ public class HttpChannelState implements HttpChannel, Components
/**
* Called when the {@link Handler} (or it's delegates) fail the request handling.
*
* @param failure The reason for the failure.
*/
@Override
@ -1679,6 +1683,7 @@ public class HttpChannelState implements HttpChannel, Components
/**
* Called when the error write in {@link HttpChannelState.ChannelCallback#failed(Throwable)} fails.
*
* @param x The reason for the failure.
*/
@Override

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.util.thread;
import java.io.Serial;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
@ -30,6 +31,7 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class AutoLock implements AutoCloseable, Serializable
{
@Serial
private static final long serialVersionUID = 3300696774541816341L;
private final ReentrantLock _lock = new ReentrantLock();
@ -46,8 +48,24 @@ public class AutoLock implements AutoCloseable, Serializable
}
/**
* @see ReentrantLock#isHeldByCurrentThread()
* <p>Tries to acquire the lock.</p>
* <p>Whether the lock was acquired can be tested
* with {@link #isHeldByCurrentThread()}.</p>
* <p>Typical usage of this method is in {@code toString()},
* to avoid deadlocks when the implementation needs to lock
* to retrieve a consistent state to produce the string.</p>
*
* @return this AutoLock for unlocking
*/
public AutoLock tryLock()
{
_lock.tryLock();
return this;
}
/**
* @return whether this lock is held by the current thread
* @see ReentrantLock#isHeldByCurrentThread()
*/
public boolean isHeldByCurrentThread()
{
@ -71,7 +89,8 @@ public class AutoLock implements AutoCloseable, Serializable
@Override
public void close()
{
_lock.unlock();
if (isHeldByCurrentThread())
_lock.unlock();
}
/**
@ -101,6 +120,12 @@ public class AutoLock implements AutoCloseable, Serializable
return (WithCondition)super.lock();
}
@Override
public AutoLock.WithCondition tryLock()
{
return (WithCondition)super.tryLock();
}
/**
* @see Condition#signal()
*/
@ -118,8 +143,8 @@ public class AutoLock implements AutoCloseable, Serializable
}
/**
* @see Condition#await()
* @throws InterruptedException if the current thread is interrupted
* @see Condition#await()
*/
public void await() throws InterruptedException
{
@ -127,11 +152,11 @@ public class AutoLock implements AutoCloseable, Serializable
}
/**
* @see Condition#await(long, TimeUnit)
* @param time the time to wait
* @param unit the time unit
* @return false if the waiting time elapsed
* @throws InterruptedException if the current thread is interrupted
* @see Condition#await(long, TimeUnit)
*/
public boolean await(long time, TimeUnit unit) throws InterruptedException
{