diff --git a/platform/platform-impl/src/com/intellij/util/io/netty.kt b/platform/platform-impl/src/com/intellij/util/io/netty.kt index 1e2de21ab30a..a09bbc552a7a 100644 --- a/platform/platform-impl/src/com/intellij/util/io/netty.kt +++ b/platform/platform-impl/src/com/intellij/util/io/netty.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -191,7 +191,7 @@ private fun connectNio(bootstrap: Bootstrap, } } -private fun sleep(promise: AsyncPromise<*>?, time: Int): Boolean { +fun sleep(promise: AsyncPromise<*>?, time: Int): Boolean { try { //noinspection BusyWait Thread.sleep(time.toLong()) diff --git a/platform/script-debugger/debugger-ui/src/RemoteVmConnection.kt b/platform/script-debugger/debugger-ui/src/RemoteVmConnection.kt index 894426810a1f..078941fc0233 100644 --- a/platform/script-debugger/debugger-ui/src/RemoteVmConnection.kt +++ b/platform/script-debugger/debugger-ui/src/RemoteVmConnection.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +22,9 @@ import com.intellij.openapi.util.Condition import com.intellij.ui.ColoredListCellRenderer import com.intellij.ui.components.JBList import com.intellij.util.io.connect +import com.intellij.util.io.sleep import com.intellij.util.io.socketConnection.ConnectionStatus import io.netty.bootstrap.Bootstrap -import io.netty.channel.ChannelFuture -import io.netty.util.concurrent.GenericFutureListener import org.jetbrains.concurrency.* import org.jetbrains.debugger.Vm import org.jetbrains.io.NettyUtil @@ -41,13 +40,9 @@ abstract class RemoteVmConnection : VmConnection() { var address: InetSocketAddress? = null private val connectCancelHandler = AtomicReference<() -> Unit>() - - protected val channelCloseListener = GenericFutureListener { - close("Process disconnected unexpectedly", ConnectionStatus.DISCONNECTED) - } - + abstract fun createBootstrap(address: InetSocketAddress, vmResult: AsyncPromise): Bootstrap - + @JvmOverloads fun open(address: InetSocketAddress, stopCondition: Condition? = null): Promise { this.address = address @@ -59,29 +54,49 @@ abstract class RemoteVmConnection : VmConnection() { if (Thread.interrupted()) { return@executeOnPooledThread } + + var attemptNumber = 0 + fun attempt() { + connectCancelHandler.set { result.setError("Closed explicitly") } - connectCancelHandler.set { result.setError("Closed explicitly") } + val connectionPromise = AsyncPromise() + connectionPromise.rejected { result.setError(it) } - val connectionPromise = AsyncPromise() - connectionPromise.rejected { result.setError(it) } - - result - .done { - vm = it!! - setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}") - startProcessing() - } - .rejected { - if (it !is ConnectException) { - LOG.errorIfNotMessage(it) + result + .done { + vm = it!! + setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}") + startProcessing() } - setState(ConnectionStatus.CONNECTION_FAILED, it.message) - } - .processed { connectCancelHandler.set(null) } + .rejected { + if (it !is ConnectException) { + LOG.errorIfNotMessage(it) + } + setState(ConnectionStatus.CONNECTION_FAILED, it.message) + } + .processed { connectCancelHandler.set(null) } - createBootstrap(address, result) - .connect(address, connectionPromise, maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1, stopCondition = stopCondition) - ?.let { it.closeFuture().addListener(channelCloseListener) } + createBootstrap(address, result) + .connect(address, connectionPromise, + maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1, + stopCondition = stopCondition) + ?.closeFuture()?.addListener { + if (result.isFulfilled) { + close("Process disconnected unexpectedly", ConnectionStatus.DISCONNECTED) + } + else { + if (++attemptNumber > 10 || (stopCondition?.value(null) ?: false)) { + result.setError("Process disconnected unexpectedly") + } + else { + sleep(result, 300) + attempt() + } + } + } + } + + attempt() } connectCancelHandler.set {