Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2012-04-26 10:56:39 -0400
committerThomas Watson2012-04-26 10:59:08 -0400
commitdeaff54d61ccd13d976388d1d28028cf2e69fe79 (patch)
treece12409d42aab4d34858b3db2763ac9261f44b09
parent29c6960ec8553d56f9796a3e6cc54a1b04324ae0 (diff)
downloadrt.equinox.framework-deaff54d61ccd13d976388d1d28028cf2e69fe79.tar.gz
rt.equinox.framework-deaff54d61ccd13d976388d1d28028cf2e69fe79.tar.xz
rt.equinox.framework-deaff54d61ccd13d976388d1d28028cf2e69fe79.zip
Bug 374272 - [ErrorHandling] Log deadlocks v20120426-1459
-rw-r--r--bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java86
1 files changed, 62 insertions, 24 deletions
diff --git a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
index 52339641d..f6a038994 100644
--- a/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
+++ b/bundles/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/equinox/log/internal/ExtendedLogReaderServiceFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 Cognos Incorporated, IBM Corporation and others
+ * Copyright (c) 2006, 2012 Cognos Incorporated, IBM Corporation and others
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
@@ -49,10 +49,10 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
private static PrintStream errorStream;
+ private final BasicReadWriteLock listenersLock = new BasicReadWriteLock();
private ArrayMap<LogListener, Object[]> listeners = new ArrayMap<LogListener, Object[]>(5);
private LogFilter[] filters = null;
-
- private BasicReadWriteLock listenersLock = new BasicReadWriteLock();
+ private final ThreadLocal<int[]> nestedCallCount = new ThreadLocal<int[]>();
static boolean safeIsLoggable(LogFilter filter, Bundle bundle, String name, int level) {
try {
@@ -116,28 +116,56 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
}
boolean isLoggablePrivileged(Bundle bundle, String name, int level) {
- int numNested = listenersLock.readLock();
+ LogFilter[] filtersCopy;
+ listenersLock.readLock();
+ try {
+ filtersCopy = filters;
+ } finally {
+ listenersLock.readUnlock();
+ }
try {
- if (numNested == MAX_RECURSIONS)
+ if (incrementNestedCount() == MAX_RECURSIONS)
return false;
- if (filters == null)
+ if (filtersCopy == null)
return false;
- if (filters == ALWAYS_LOG)
+ if (filtersCopy == ALWAYS_LOG)
return true;
- int filtersLength = filters.length;
+ int filtersLength = filtersCopy.length;
for (int i = 0; i < filtersLength; i++) {
- LogFilter filter = filters[i];
+ LogFilter filter = filtersCopy[i];
if (safeIsLoggable(filter, bundle, name, level))
return true;
}
} finally {
- listenersLock.readUnlock();
+ decrementNestedCount();
}
return false;
}
+ private int incrementNestedCount() {
+ int[] count = getCount();
+ count[0] = count[0] + 1;
+ return count[0];
+ }
+
+ private void decrementNestedCount() {
+ int[] count = getCount();
+ if (count[0] == 0)
+ return;
+ count[0] = count[0] - 1;
+ }
+
+ private int[] getCount() {
+ int[] count = nestedCallCount.get();
+ if (count == null) {
+ count = new int[] {0};
+ nestedCallCount.set(count);
+ }
+ return count;
+ }
+
void log(final Bundle bundle, final String name, final Object context, final int level, final String message, final Throwable exception) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -153,16 +181,22 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
void logPrivileged(Bundle bundle, String name, Object context, int level, String message, Throwable exception) {
LogEntry logEntry = new ExtendedLogEntryImpl(bundle, name, context, level, message, exception);
- int numNested = listenersLock.readLock();
+ ArrayMap<LogListener, Object[]> listenersCopy;
+ listenersLock.readLock();
try {
- if (numNested >= MAX_RECURSIONS)
+ listenersCopy = listeners;
+ } finally {
+ listenersLock.readUnlock();
+ }
+ try {
+ if (incrementNestedCount() >= MAX_RECURSIONS)
return;
- int size = listeners.size();
+ int size = listenersCopy.size();
for (int i = 0; i < size; i++) {
- Object[] listenerObjects = listeners.getValue(i);
+ Object[] listenerObjects = listenersCopy.getValue(i);
LogFilter filter = (LogFilter) listenerObjects[0];
if (safeIsLoggable(filter, bundle, name, level)) {
- LogListener listener = listeners.getKey(i);
+ LogListener listener = listenersCopy.getKey(i);
SerializedTaskQueue taskQueue = (SerializedTaskQueue) listenerObjects[1];
if (taskQueue != null) {
taskQueue.put(new LogTask(logEntry, listener));
@@ -173,14 +207,15 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
}
}
} finally {
- listenersLock.readUnlock();
+ decrementNestedCount();
}
}
void addLogListener(LogListener listener, LogFilter filter) {
listenersLock.writeLock();
try {
- Object[] listenerObjects = listeners.get(listener);
+ ArrayMap<LogListener, Object[]> listenersCopy = new ArrayMap<LogListener, Object[]>(listeners.getKeys(), listeners.getValues());
+ Object[] listenerObjects = listenersCopy.get(listener);
if (listenerObjects == null) {
// Only create a task queue for non-SynchronousLogListeners
SerializedTaskQueue taskQueue = (listener instanceof SynchronousLogListener) ? null : new SerializedTaskQueue(listener.toString());
@@ -189,18 +224,19 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
// update the filter
listenerObjects[0] = filter;
}
- listeners.put(listener, listenerObjects);
- recalculateFilters();
+ listenersCopy.put(listener, listenerObjects);
+ recalculateFilters(listenersCopy);
+ listeners = listenersCopy;
} finally {
listenersLock.writeUnlock();
}
}
- private void recalculateFilters() {
+ private void recalculateFilters(ArrayMap<LogListener, Object[]> listenersCopy) {
List<LogFilter> filtersList = new ArrayList<LogFilter>();
- int size = listeners.size();
+ int size = listenersCopy.size();
for (int i = 0; i < size; i++) {
- Object[] listenerObjects = listeners.getValue(i);
+ Object[] listenerObjects = listenersCopy.getValue(i);
LogFilter filter = (LogFilter) listenerObjects[0];
if (filter == NULL_LOGGER_FILTER) {
filters = ALWAYS_LOG;
@@ -218,8 +254,10 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
void removeLogListener(LogListener listener) {
listenersLock.writeLock();
try {
- listeners.remove(listener);
- recalculateFilters();
+ ArrayMap<LogListener, Object[]> listenersCopy = new ArrayMap<LogListener, Object[]>(listeners.getKeys(), listeners.getValues());
+ listenersCopy.remove(listener);
+ recalculateFilters(listenersCopy);
+ listeners = listenersCopy;
} finally {
listenersLock.writeUnlock();
}

Back to the top