tone down error logging in IO layer, see #3386
* Made defaultDecider available in SupervisorStrategy,
turned out that I didn't need it but I think it could be
good anyway, e.g.
override def supervisorStrategy = OneForOneStrategy(
enableLogging = false)(SupervisorStrategy.defaultDecider)
* Verified the following scenarios:
- client connection failure
- server bind failure
- kill client (peer closed)
- kill server (peer closed)
This commit is contained in:
parent
51ed174432
commit
9b59187816
9 changed files with 55 additions and 34 deletions
|
|
@ -527,14 +527,12 @@ class TcpConnectionSpec extends AkkaSpec("""
|
|||
run {
|
||||
localServerChannel.accept()
|
||||
|
||||
EventFilter.warning(pattern = "registration timeout", occurrences = 1) intercept {
|
||||
selector.send(connectionActor, ChannelConnectable)
|
||||
userHandler.expectMsg(Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
||||
|
||||
verifyActorTermination(connectionActor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"close the connection when user handler dies while connecting" in new UnacceptedConnectionTest {
|
||||
run {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package akka.io
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import akka.testkit.AkkaSpec
|
||||
import akka.util.ByteString
|
||||
import Tcp._
|
||||
|
|
@ -32,9 +33,7 @@ class TcpIntegrationSpec extends AkkaSpec("""
|
|||
|
||||
"properly handle connection abort from one side" in new TestSetup {
|
||||
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
|
||||
EventFilter[IOException](occurrences = 1) intercept {
|
||||
clientHandler.send(clientConnection, Abort)
|
||||
}
|
||||
clientHandler.expectMsg(Aborted)
|
||||
serverHandler.expectMsgType[ErrorClosed]
|
||||
verifyActorTermination(clientConnection)
|
||||
|
|
|
|||
|
|
@ -145,20 +145,27 @@ object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits {
|
|||
|
||||
/**
|
||||
* When supervisorStrategy is not specified for an actor this
|
||||
* is used by default. The child will be stopped when
|
||||
* [[akka.actor.ActorInitializationException]] or [[akka.ActorKilledException]]
|
||||
* is thrown. It will be restarted for other `Exception` types.
|
||||
* The error is escalated if it's a `Throwable`, i.e. `Error`.
|
||||
* is used by default. OneForOneStrategy with decider defined in
|
||||
* [[#defaultDecider]].
|
||||
*/
|
||||
final val defaultStrategy: SupervisorStrategy = {
|
||||
def defaultDecider: Decider = {
|
||||
OneForOneStrategy()(defaultDecider)
|
||||
}
|
||||
|
||||
/**
|
||||
* When supervisorStrategy is not specified for an actor this
|
||||
* [[Decider]] is used by default in the supervisor strategy.
|
||||
* The child will be stopped when [[akka.actor.ActorInitializationException]],
|
||||
* [[akka.ActorKilledException]], or [[akka.actor.DeathPactException]] is
|
||||
* thrown. It will be restarted for other `Exception` types.
|
||||
* The error is escalated if it's a `Throwable`, i.e. `Error`.
|
||||
*/
|
||||
final def defaultDecider: Decider = {
|
||||
case _: ActorInitializationException ⇒ Stop
|
||||
case _: ActorKilledException ⇒ Stop
|
||||
case _: DeathPactException ⇒ Stop
|
||||
case _: Exception ⇒ Restart
|
||||
}
|
||||
OneForOneStrategy()(defaultDecider)
|
||||
}
|
||||
|
||||
/**
|
||||
* This strategy resembles Erlang in that failing children are always
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ private[io] object SelectionHandler {
|
|||
def tryRun(): Unit = {
|
||||
// thorough 'close' of the Selector
|
||||
@tailrec def closeNextChannel(it: JIterator[SelectionKey]): Unit = if (it.hasNext) {
|
||||
try it.next().channel.close() catch { case NonFatal(e) ⇒ log.error(e, "Error closing channel") }
|
||||
try it.next().channel.close() catch { case NonFatal(e) ⇒ log.debug("Error closing channel: {}", e) }
|
||||
closeNextChannel(it)
|
||||
}
|
||||
try closeNextChannel(selector.keys.iterator)
|
||||
|
|
@ -246,7 +246,24 @@ private[io] class SelectionHandler(settings: SelectionHandlerSettings) extends A
|
|||
override def postStop(): Unit = registry.shutdown()
|
||||
|
||||
// we can never recover from failures of a connection or listener child
|
||||
override def supervisorStrategy = SupervisorStrategy.stoppingStrategy
|
||||
// and log the failure at debug level
|
||||
override def supervisorStrategy = {
|
||||
def stoppingDecider: SupervisorStrategy.Decider = {
|
||||
case _: Exception ⇒ SupervisorStrategy.Stop
|
||||
}
|
||||
new OneForOneStrategy()(stoppingDecider) {
|
||||
override protected def logFailure(context: ActorContext, child: ActorRef, cause: Throwable,
|
||||
decision: SupervisorStrategy.Directive): Unit =
|
||||
try {
|
||||
val logMessage = cause match {
|
||||
case e: ActorInitializationException if e.getCause ne null ⇒ e.getCause.getMessage
|
||||
case e ⇒ e.getMessage
|
||||
}
|
||||
context.system.eventStream.publish(
|
||||
Logging.Debug(child.path.toString, classOf[SelectionHandler], logMessage))
|
||||
} catch { case NonFatal(_) ⇒ }
|
||||
}
|
||||
}
|
||||
|
||||
def spawnChildWithCapacityProtection(cmd: WorkerForCommand, retriesLeft: Int): Unit = {
|
||||
if (TraceLogging) log.debug("Executing [{}]", cmd)
|
||||
|
|
@ -258,7 +275,7 @@ private[io] class SelectionHandler(settings: SelectionHandlerSettings) extends A
|
|||
if (MaxChannelsPerSelector > 0) context.watch(child) // we don't need to watch if we aren't limited
|
||||
} else {
|
||||
if (retriesLeft >= 1) {
|
||||
log.warning("Rejecting [{}] with [{}] retries left, retrying...", cmd, retriesLeft)
|
||||
log.debug("Rejecting [{}] with [{}] retries left, retrying...", cmd, retriesLeft)
|
||||
context.parent forward Retry(cmd, retriesLeft - 1)
|
||||
} else {
|
||||
log.warning("Rejecting [{}] with no retries left, aborting...", cmd)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ private[io] abstract class TcpConnection(val tcp: TcpExt, val channel: SocketCha
|
|||
case ReceiveTimeout ⇒
|
||||
// after sending `Register` user should watch this actor to make sure
|
||||
// it didn't die because of the timeout
|
||||
log.warning("Configured registration timeout of [{}] expired, stopping", RegisterTimeout)
|
||||
log.debug("Configured registration timeout of [{}] expired, stopping", RegisterTimeout)
|
||||
context.stop(self)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ private[io] class TcpListener(selectorRouter: ActorRef,
|
|||
} catch {
|
||||
case NonFatal(e) ⇒
|
||||
bindCommander ! bind.failureMessage
|
||||
log.error(e, "Bind failed for TCP channel on endpoint [{}]", bind.localAddress)
|
||||
log.debug("Bind failed for TCP channel on endpoint [{}]: {}", bind.localAddress, e)
|
||||
context.stop(self)
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ private[io] class TcpListener(selectorRouter: ActorRef,
|
|||
log.warning("Could not register incoming connection since selector capacity limit is reached, closing connection")
|
||||
try socketChannel.close()
|
||||
catch {
|
||||
case NonFatal(e) ⇒ log.error(e, "Error closing channel")
|
||||
case NonFatal(e) ⇒ log.debug("Error closing socket channel: {}", e)
|
||||
}
|
||||
|
||||
case Unbind ⇒
|
||||
|
|
@ -95,7 +95,7 @@ private[io] class TcpListener(selectorRouter: ActorRef,
|
|||
if (limit > 0) {
|
||||
try channel.accept()
|
||||
catch {
|
||||
case NonFatal(e) ⇒ { log.error(e, "Accept error: could not accept new connection due to {}", e); null }
|
||||
case NonFatal(e) ⇒ { log.error(e, "Accept error: could not accept new connection"); null }
|
||||
}
|
||||
} else null
|
||||
if (socketChannel != null) {
|
||||
|
|
@ -115,7 +115,7 @@ private[io] class TcpListener(selectorRouter: ActorRef,
|
|||
channel.close()
|
||||
}
|
||||
} catch {
|
||||
case NonFatal(e) ⇒ log.error(e, "Error closing ServerSocketChannel")
|
||||
case NonFatal(e) ⇒ log.debug("Error closing ServerSocketChannel: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ private[io] class UdpConnection(udpConn: UdpConnectedExt,
|
|||
datagramChannel.connect(remoteAddress)
|
||||
} catch {
|
||||
case NonFatal(e) ⇒
|
||||
log.error(e, "Failure while connecting UDP channel to remote address [{}] local address [{}]",
|
||||
remoteAddress, localAddress.map { _.toString }.getOrElse("undefined"))
|
||||
log.debug("Failure while connecting UDP channel to remote address [{}] local address [{}]: {}",
|
||||
remoteAddress, localAddress.getOrElse("undefined"), e)
|
||||
commander ! CommandFailed(connect)
|
||||
context.stop(self)
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ private[io] class UdpConnection(udpConn: UdpConnectedExt,
|
|||
log.debug("Closing DatagramChannel after being stopped")
|
||||
try channel.close()
|
||||
catch {
|
||||
case NonFatal(e) ⇒ log.error(e, "Error closing DatagramChannel")
|
||||
case NonFatal(e) ⇒ log.debug("Error closing DatagramChannel: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ private[io] class UdpListener(val udp: UdpExt,
|
|||
} catch {
|
||||
case NonFatal(e) ⇒
|
||||
bindCommander ! CommandFailed(bind)
|
||||
log.error(e, "Failed to bind UDP channel to endpoint [{}]", bind.localAddress)
|
||||
log.debug("Failed to bind UDP channel to endpoint [{}]: {}", bind.localAddress, e)
|
||||
context.stop(self)
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ private[io] class UdpListener(val udp: UdpExt,
|
|||
log.debug("Closing DatagramChannel after being stopped")
|
||||
try channel.close()
|
||||
catch {
|
||||
case NonFatal(e) ⇒ log.error(e, "Error closing DatagramChannel")
|
||||
case NonFatal(e) ⇒ log.debug("Error closing DatagramChannel: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ private[io] class UdpSender(val udp: UdpExt,
|
|||
log.debug("Closing DatagramChannel after being stopped")
|
||||
try channel.close()
|
||||
catch {
|
||||
case NonFatal(e) ⇒ log.error(e, "Error closing DatagramChannel")
|
||||
case NonFatal(e) ⇒ log.debug("Error closing DatagramChannel: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue