mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX to HEAD (4.2)
55489: Merged V4.1-BUG-FIX (4.1.7) to HEAD-BUG-FIX (4.2) 55002: Improved handling of deadlocks and improved test - MNT-9517 Deadlock when binding class behaviours during bootstrap - MNT-9462 : WebContainer threads are deadlocked Added the LockTryException to RetryingTransactionHelper Test was waiting 1s for lock resolution, which would have been fine if it didn't also have to include actual dictionary/message initialization. I also changed deadlock threads so that they run with full retrying and ensure that both threads succeed despite the deadlock. To observe, run the MessageServiceImplTest with the following: log4j.logger.org.alfresco.repo.transaction.RetryingTransactionHelper=TRACE git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@55777 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -37,6 +37,7 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
|||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
@@ -428,49 +429,97 @@ public class MessageServiceImplTest extends TestCase implements MessageDeployer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See MNT-9462
|
* See MNT-9462
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void testDictionaryDAOLock()
|
public void testDictionaryDAOLock()
|
||||||
{
|
{
|
||||||
class DictionaryDAOThread extends Thread
|
class DictionaryDAOThread extends Thread
|
||||||
{
|
{
|
||||||
|
private volatile boolean success = false;
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
dictionaryDAO.destroy();
|
success = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Boolean>()
|
||||||
dictionaryDAO.init();
|
{
|
||||||
|
@Override
|
||||||
|
public Boolean execute() throws Throwable
|
||||||
|
{
|
||||||
|
dictionaryDAO.destroy();
|
||||||
|
dictionaryDAO.init();
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MessageServiceThread extends Thread
|
class MessageServiceThread extends Thread
|
||||||
{
|
{
|
||||||
|
private volatile boolean success = false;
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
messageService.destroy();
|
success = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Boolean>()
|
||||||
messageService.getMessage(MSG_YES);
|
{
|
||||||
|
@Override
|
||||||
|
public Boolean execute()
|
||||||
|
{
|
||||||
|
messageService.destroy();
|
||||||
|
messageService.getMessage(MSG_YES);
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Create the threads so that they die if the VM exits
|
||||||
DictionaryDAOThread ddt = new DictionaryDAOThread();
|
DictionaryDAOThread ddt = new DictionaryDAOThread();
|
||||||
|
ddt.setDaemon(true);
|
||||||
MessageServiceThread mst = new MessageServiceThread();
|
MessageServiceThread mst = new MessageServiceThread();
|
||||||
|
mst.setDaemon(true);
|
||||||
|
|
||||||
ddt.start();
|
ddt.start();
|
||||||
mst.start();
|
mst.start();
|
||||||
|
// Wait for the first thread to
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ddt.join(1000);
|
ddt.join(60000);
|
||||||
mst.join(1000);
|
mst.join(60000);
|
||||||
}
|
}
|
||||||
catch (InterruptedException ie)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
|
// Interrupt to terminate any lock trying
|
||||||
ddt.interrupt();
|
ddt.interrupt();
|
||||||
mst.interrupt();
|
mst.interrupt();
|
||||||
fail("Threads were deadlocked.");
|
// Something kicked us out before we could join and before the time expired ... unlikely
|
||||||
|
fail("Unexpected interrupt while joining to deadlocking threads.");
|
||||||
}
|
}
|
||||||
if (ddt.isAlive() || mst.isAlive())
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
ddt.stop();
|
if (ddt.isAlive() && mst.isAlive())
|
||||||
mst.stop();
|
{
|
||||||
fail("Threads were deadlocked.");
|
fail("Deadlock: DictionaryDAOThread and MessageServiceThread are both still alive.");
|
||||||
|
}
|
||||||
|
else if (ddt.isAlive())
|
||||||
|
{
|
||||||
|
fail("Possible deadlock with a background process: DictionaryDAOThread is still alive.");
|
||||||
|
}
|
||||||
|
else if (mst.isAlive())
|
||||||
|
{
|
||||||
|
fail("Possible deadlock with a background process: MessageServiceThread is still alive.");
|
||||||
|
}
|
||||||
|
else if (!ddt.success)
|
||||||
|
{
|
||||||
|
fail("DictionaryDAOThread failed to execute successfully.");
|
||||||
|
}
|
||||||
|
else if (!mst.success)
|
||||||
|
{
|
||||||
|
fail("MessageServiceThread failed to execute successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Interrupt to terminate any lock trying
|
||||||
|
ddt.interrupt();
|
||||||
|
mst.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user