From 86eb25d344633ca424d4206e030371df4455c290 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 22 Nov 2015 17:29:03 +0300 Subject: [PATCH] IDEA-143358 Unregister authenticators on project dispose if they don't get unregistered for some reason HTTP and SSH Authenticators hold a link to the Project, while the GitXmlRpcHandlerService is application wide. Normally, authenticators are unregistered on Git processTerminated, or if an exception happens. But if some reason this doesn't happen, we want to make sure that the Project doesn't leak. --- .../src/git4idea/commands/GitHandler.java | 4 ++-- .../git4idea/ssh/GitXmlRpcHandlerService.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index e37db82a7df2..c6e68ff0c25b 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -456,7 +456,7 @@ public abstract class GitHandler { GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath()); GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, ObjectUtils.assertNotNull(myUrls)); - myHttpHandler = service.registerHandler(httpAuthenticator); + myHttpHandler = service.registerHandler(httpAuthenticator, myProject); myEnvironmentCleanedUp = false; myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHttpHandler)); int port = service.getXmlRcpPort(); @@ -468,7 +468,7 @@ public abstract class GitHandler { private void setupSshAuthenticator() throws IOException { GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); - mySshHandler = ssh.registerHandler(new GitSSHGUIHandler(myProject)); + mySshHandler = ssh.registerHandler(new GitSSHGUIHandler(myProject), myProject); myEnvironmentCleanedUp = false; myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(mySshHandler)); int port = ssh.getXmlRcpPort(); diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java index 6e4a6721de16..12c99d9d26ad 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java @@ -16,6 +16,8 @@ package org.jetbrains.git4idea.ssh; import com.intellij.ide.XmlRpcServer; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtilRt; import gnu.trove.THashMap; import org.apache.commons.codec.DecoderException; @@ -105,18 +107,25 @@ public abstract class GitXmlRpcHandlerService { /** * Register handler. Note that handlers must be unregistered using {@link #unregisterHandler(int)}. * - * @param handler a handler to register + * @param handler a handler to register + * @param parentDisposable a disposable to unregister the handler if it doesn't get unregistered manually * @return an identifier to pass to the environment variable */ - public int registerHandler(@NotNull T handler) { + public int registerHandler(@NotNull T handler, @NotNull Disposable parentDisposable) { synchronized (HANDLERS_LOCK) { XmlRpcServer xmlRpcServer = XmlRpcServer.SERVICE.getInstance(); if (!xmlRpcServer.hasHandler(myHandlerName)) { xmlRpcServer.addHandler(myHandlerName, createRpcRequestHandlerDelegate()); } - int key = myNextHandlerKey; + final int key = myNextHandlerKey; handlers.put(key, handler); + Disposer.register(parentDisposable, new Disposable() { + @Override + public void dispose() { + handlers.remove(key); + } + }); myNextHandlerKey++; return key; }