mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] AppMain improvements: reversed socket direction to avoid port probing
This commit is contained in:
@@ -21,8 +21,11 @@ import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.execution.configurations.ParametersList;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ProcessProxyFactoryImpl extends ProcessProxyFactory {
|
||||
private static final String DONT_USE_LAUNCHER_PROPERTY = "idea.no.launcher";
|
||||
|
||||
@@ -34,15 +37,19 @@ public class ProcessProxyFactoryImpl extends ProcessProxyFactory {
|
||||
if (mainClass != null) {
|
||||
try {
|
||||
ProcessProxyImpl proxy = new ProcessProxyImpl();
|
||||
|
||||
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
||||
ParametersList vmParametersList = javaParameters.getVMParametersList();
|
||||
vmParametersList.defineProperty(ProcessProxyImpl.PROPERTY_PORT_NUMBER, String.valueOf(proxy.getPortNumber()));
|
||||
vmParametersList.defineProperty(ProcessProxyImpl.PROPERTY_BIN_PATH, PathManager.getBinPath());
|
||||
|
||||
javaParameters.getProgramParametersList().prepend(mainClass);
|
||||
javaParameters.setMainClass(ProcessProxyImpl.LAUNCH_MAIN_CLASS);
|
||||
return proxy;
|
||||
}
|
||||
catch (ProcessProxyImpl.NoMoreSocketsException ignored) { }
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(ProcessProxy.class).warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,17 @@ package com.intellij.execution.runners;
|
||||
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -36,66 +39,46 @@ class ProcessProxyImpl implements ProcessProxy {
|
||||
public static final String PROPERTY_PORT_NUMBER = "idea.launcher.port";
|
||||
public static final String LAUNCH_MAIN_CLASS = "com.intellij.rt.execution.application.AppMain";
|
||||
|
||||
private static final int SOCKET_NUMBER_START = 7532;
|
||||
private static final int SOCKET_NUMBER = 100;
|
||||
private static final boolean[] ourUsedSockets = new boolean[SOCKET_NUMBER];
|
||||
private final ServerSocket mySocket;
|
||||
private Writer myWriter;
|
||||
|
||||
private final int myPortNumber;
|
||||
private PrintWriter myWriter;
|
||||
private Socket mySocket;
|
||||
|
||||
public static class NoMoreSocketsException extends Exception { }
|
||||
|
||||
public ProcessProxyImpl() throws NoMoreSocketsException {
|
||||
myPortNumber = findFreePort();
|
||||
if (myPortNumber == -1) throw new NoMoreSocketsException();
|
||||
}
|
||||
|
||||
private static int findFreePort() {
|
||||
synchronized (ourUsedSockets) {
|
||||
for (int j = 0; j < SOCKET_NUMBER; j++) {
|
||||
if (ourUsedSockets[j]) continue;
|
||||
try {
|
||||
ServerSocket s = new ServerSocket(j + SOCKET_NUMBER_START);
|
||||
s.close();
|
||||
ourUsedSockets[j] = true;
|
||||
return j + SOCKET_NUMBER_START;
|
||||
}
|
||||
catch (IOException ignore) { }
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
public ProcessProxyImpl() throws IOException {
|
||||
mySocket = new ServerSocket();
|
||||
mySocket.bind(new InetSocketAddress("127.0.0.1", 0));
|
||||
mySocket.setSoTimeout(10000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPortNumber() {
|
||||
return myPortNumber;
|
||||
return mySocket.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach(@NotNull ProcessHandler processHandler) {
|
||||
public synchronized void attach(@NotNull ProcessHandler processHandler) {
|
||||
processHandler.putUserData(KEY, this);
|
||||
try {
|
||||
//noinspection SocketOpenedButNotSafelyClosed
|
||||
myWriter = new OutputStreamWriter(mySocket.accept().getOutputStream(), "US-ASCII");
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(ProcessProxy.class).warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"SocketOpenedButNotSafelyClosed", "IOResourceOpenedButNotSafelyClosed"})
|
||||
private synchronized void writeLine(String s) {
|
||||
if (myWriter == null) {
|
||||
try {
|
||||
if (mySocket == null) {
|
||||
mySocket = new Socket(InetAddress.getLoopbackAddress(), myPortNumber);
|
||||
}
|
||||
myWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mySocket.getOutputStream())));
|
||||
}
|
||||
catch (IOException e) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
myWriter.write(s);
|
||||
myWriter.write('\n');
|
||||
myWriter.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(ProcessProxy.class).warn(e);
|
||||
}
|
||||
myWriter.println(s);
|
||||
myWriter.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSendBreak() {
|
||||
public synchronized boolean canSendBreak() {
|
||||
if (myWriter == null) return false;
|
||||
String libName = null;
|
||||
if (SystemInfo.isWindows) libName = "breakgen.dll";
|
||||
else if (SystemInfo.isMac) libName = "libbreakgen.jnilib";
|
||||
@@ -103,6 +86,11 @@ class ProcessProxyImpl implements ProcessProxy {
|
||||
return libName != null && new File(PathManager.getBinPath(), libName).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean canSendStop() {
|
||||
return myWriter != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBreak() {
|
||||
writeLine("BREAK");
|
||||
@@ -115,9 +103,14 @@ class ProcessProxyImpl implements ProcessProxy {
|
||||
|
||||
@Override
|
||||
public synchronized void destroy() {
|
||||
if (myWriter != null) {
|
||||
myWriter.close();
|
||||
try {
|
||||
if (myWriter != null) {
|
||||
myWriter.close();
|
||||
}
|
||||
mySocket.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(ProcessProxy.class).warn(e);
|
||||
}
|
||||
ourUsedSockets[myPortNumber - SOCKET_NUMBER_START] = false;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import java.io.InputStreamReader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -70,37 +69,31 @@ public class AppMain {
|
||||
Thread t = new Thread("Monitor Ctrl-Break") {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket socket = new ServerSocket(portNumber);
|
||||
Socket client = new Socket("127.0.0.1", portNumber);
|
||||
try {
|
||||
Socket client = socket.accept();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"));
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
|
||||
try {
|
||||
while (true) {
|
||||
String msg = reader.readLine();
|
||||
if ("TERM".equals(msg)) {
|
||||
return;
|
||||
}
|
||||
else if ("BREAK".equals(msg)) {
|
||||
if (ourHelperLibLoaded) {
|
||||
triggerControlBreak();
|
||||
}
|
||||
}
|
||||
else if ("STOP".equals(msg)) {
|
||||
System.exit(1);
|
||||
while (true) {
|
||||
String msg = reader.readLine();
|
||||
if ("TERM".equals(msg)) {
|
||||
return;
|
||||
}
|
||||
else if ("BREAK".equals(msg)) {
|
||||
if (ourHelperLibLoaded) {
|
||||
triggerControlBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
else if ("STOP".equals(msg)) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
client.close();
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
socket.close();
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
|
||||
Reference in New Issue
Block a user