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:
Alan Davis
2013-09-20 20:45:36 +00:00
parent b4dbcde79d
commit e5e97719b3

View File

@@ -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();
} }
} }
} }