GP-4531 Corrected Ghidra Server deadlock

This commit is contained in:
ghidra1 2024-04-18 11:58:33 -04:00
parent bf01521402
commit feaf8e2d49
2 changed files with 60 additions and 86 deletions

View File

@ -36,18 +36,20 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
implements RemoteBufferFileHandle, Unreferenced {
// Tracks open handles by user repository connection: maps repository handle instance to list of open file handles
private static HashMap<RemoteRepositoryHandle, List<RemoteBufferFileImpl>> instanceOwnerMap =
private static final HashMap<RemoteRepositoryHandle, List<RemoteBufferFileImpl>> instanceOwnerMap =
new HashMap<>();
// Tracks open handles by path: maps "repo-name:<file-path>" to list of open buffer file handles
private static HashMap<String, List<RemoteBufferFileImpl>> instancePathMap = new HashMap<>();
private static final HashMap<String, List<RemoteBufferFileImpl>> instancePathMap =
new HashMap<>();
protected final RepositoryHandleImpl owner;
protected final String associatedFilePath;
private LocalBufferFile bufferFile;
private final String clientHost;
private final LocalBufferFile bufferFile;
private boolean disposed = false;
private String clientHost;
/**
* Construct a remote wrapper for a buffer file.
@ -68,7 +70,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
}
this.clientHost = RepositoryManager.getRMIClient();
addInstance(this);
//System.out.println("Constructed remote buffer file (" + instanceID + "): " + bufferFile);
}
private static String getFilePathKey(RemoteBufferFileImpl rbf) {
@ -95,7 +96,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
instancePathMap.put(filePathKey, list);
}
list.add(rbf);
rbf.owner.fireOpenFileCountChanged();
}
private static synchronized void removeOwnerInstance(RemoteBufferFileImpl rbf) {
@ -104,7 +104,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
if (list.isEmpty()) {
instanceOwnerMap.remove(rbf.owner);
}
rbf.owner.fireOpenFileCountChanged();
}
}
@ -118,6 +117,29 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
}
}
/**
* Dispose and unexport all RemoteBufferFileImpl instances associated with the
* specified owner.
* @param owner
* @return true if one or more buffer files were disposed.
*/
public static synchronized boolean dispose(Object owner) {
boolean found = false;
List<RemoteBufferFileImpl> list = instanceOwnerMap.remove(owner);
if (list != null) {
for (RemoteBufferFileImpl rbf : list) {
found = true;
rbf.dispose();
}
}
if (found) {
// If files were found, may need to repeat since pre-save
// files may have been constructed during dispose
dispose(owner);
}
return found;
}
/**
* Get the number of open RemoteBufferFileHandle's associated with the
* specified owner repository handle.
@ -172,46 +194,26 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
dispose();
}
/**
* Dispose and unexport all RemoteBufferFileImpl instances associated with the
* specified owner.
* @param owner
* @return true if one or more buffer files were disposed.
*/
public static synchronized boolean dispose(Object owner) {
boolean found = false;
List<RemoteBufferFileImpl> list = instanceOwnerMap.remove(owner);
if (list != null) {
for (RemoteBufferFileImpl rbf : list) {
found = true;
rbf.dispose();
}
}
if (found) {
// If files were found, may need to repeat since pre-save
// files may have been constructed during dispose
dispose(owner);
}
return found;
}
/**
* Dispose associated buffer file and unexport this instance.
*/
@Override
public synchronized void dispose() {
// must handle concurrent invocations
if (!disposed) {
try {
unexportObject(this, true);
public void dispose() {
removeOwnerInstance(this);
removePathInstance(this);
synchronized (this) {
if (!disposed) {
try {
unexportObject(this, true);
}
catch (NoSuchObjectException e) {
// ignore
}
bufferFile.dispose();
disposed = true;
}
catch (NoSuchObjectException e) {
// ignore
}
removeOwnerInstance(this);
removePathInstance(this);
bufferFile.dispose();
disposed = true;
}
}

View File

@ -39,8 +39,8 @@ import ghidra.util.exception.FileInUseException;
* <code>RepositoryHandleImpl</code> provides a Repository handle to a
* remote user.
*/
public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteRepositoryHandle,
Unreferenced {
public class RepositoryHandleImpl extends UnicastRemoteObject
implements RemoteRepositoryHandle, Unreferenced {
// private final RepositoryChangeEvent NULL_EVENT = new RepositoryChangeEvent(
// RepositoryChangeEvent.REP_NULL_EVENT, null, null, null, null);
@ -191,8 +191,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
RepositoryChangeEvent openFileCountEvent =
new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null,
null, Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null, null,
Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
synchronized (eventQueue) {
if (clientActive) {
@ -213,31 +213,6 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
dispose();
}
public void fireOpenFileCountChanged() {
// if (!isValid) {
// return;
// }
//
// RepositoryChangeEvent event =
// new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null,
// null, Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
// synchronized (eventQueue) {
//
// // Remove existing queued event
// Iterator<RepositoryChangeEvent> iterator = eventQueue.iterator();
// while (iterator.hasNext()) {
// RepositoryChangeEvent queuedEvent = iterator.next();
// if (queuedEvent.type == RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT) {
// iterator.remove();
// break;
// }
// }
//
// eventQueue.add(event);
// eventQueue.notifyAll();
// }
}
@Override
public RepositoryChangeEvent[] getEvents() throws IOException {
synchronized (eventQueue) {
@ -414,16 +389,15 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
if (folder == null) {
throw new IOException("Failed to create repository Folder " + parentPath);
}
LocalManagedBufferFile bf =
folder.createDatabase(itemName, fileID, bufferSize, contentType, currentUser,
projectPath);
LocalManagedBufferFile bf = folder.createDatabase(itemName, fileID, bufferSize,
contentType, currentUser, projectPath);
return new RemoteManagedBufferFileImpl(bf, this, getPathname(parentPath, itemName));
}
}
@Override
public RemoteManagedBufferFileImpl openDatabase(String parentPath, String itemName,
int version, int minChangeDataVer) throws IOException {
public RemoteManagedBufferFileImpl openDatabase(String parentPath, String itemName, int version,
int minChangeDataVer) throws IOException {
synchronized (syncObject) {
validate();
RepositoryFile rf = getFile(parentPath, itemName);
@ -481,9 +455,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
validate();
repository.validateWritePrivilege(currentUser);
checkFolderInUse(oldParentPath, oldFolderName);
RepositoryFolder folder =
repository.getFolder(currentUser, oldParentPath + FileSystem.SEPARATOR +
oldFolderName, false);
RepositoryFolder folder = repository.getFolder(currentUser,
oldParentPath + FileSystem.SEPARATOR + oldFolderName, false);
RepositoryFolder newParent = repository.getFolder(currentUser, newParentPath, true);
if (folder != null) {
folder.moveTo(newParent, newFolderName, currentUser);
@ -511,9 +484,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
private void checkFileInUse(String parentPath, String itemName) throws FileInUseException {
String[] openFileUsers =
RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
getPathname(parentPath, itemName));
String[] openFileUsers = RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
getPathname(parentPath, itemName));
if (openFileUsers != null) {
StringBuffer buf = new StringBuffer("");
for (String user : openFileUsers) {
@ -553,9 +525,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
if (rf.hasCheckouts()) {
return true;
}
String[] openFileUsers =
RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
getPathname(folder.getPathname(), rf.getName()));
String[] openFileUsers = RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
getPathname(folder.getPathname(), rf.getName()));
if (openFileUsers != null) {
return true;
}
@ -622,7 +593,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
@Override
public ItemCheckoutStatus[] getCheckouts(String parentPath, String itemName) throws IOException {
public ItemCheckoutStatus[] getCheckouts(String parentPath, String itemName)
throws IOException {
synchronized (syncObject) {
validate();
RepositoryFile rf = getFile(parentPath, itemName);