Fixes bug in RandomRouter.

Fixes an interesting "bug" in RandomRouter. Tests failed on my 12 core Linux box. After some investigation I found that it hanged randomly inside the SecureRandom seed generator.

[JVM-Node4] "main" prio=10 tid=0x0000000001701000 nid=0x1942 runnable [0x00007fee631dc000]
[JVM-Node4]    java.lang.Thread.State: RUNNABLE
[JVM-Node4]   at java.io.FileInputStream.readBytes(Native Method)
[JVM-Node4]   at java.io.FileInputStream.read(FileInputStream.java:236)
[JVM-Node4]   at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedBytes(SeedGenerator.java:509)
[JVM-Node4]   at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:135)
[JVM-Node4]   at sun.security.provider.SecureRandom.engineGenerateSeed(SecureRandom.java:131)
[JVM-Node4]   at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:188)
[JVM-Node4]   - locked <0x00000007c3d84130> (a sun.security.provider.SecureRandom)
[JVM-Node4]   at java.security.SecureRandom.nextBytes(SecureRandom.java:450)
[JVM-Node4]   - locked <0x00000007c3d843d0> (a java.security.SecureRandom)
[JVM-Node4]   at java.security.SecureRandom.next(SecureRandom.java:472)
[JVM-Node4]   at java.util.Random.nextInt(Random.java:272)
[JVM-Node4]   at akka.routing.RandomLike$class.getNext$2(Routing.scala:466)

Puzzled at first I Googled the problem and found this bug report: http://bugs.sun.com/view_bug.do?bug_id=6521844

In short it is designed to block on /dev/random (on Linux) when the entropy pool is empty until some "environmental noise is gathered".

From the Linux manual:
"Hanging at generateSeed is not a bug, since that's what was designed:
    When the entropy pool is empty, reads from /dev/random will block until
    additional environmental noise is gathered.
    (Source: Linux Programmer's Manual, section 4)"

Fix was to switch to java.util.Random.

Fun one

Signed-off-by: Jonas Bonér <jonas@jonasboner.com>
This commit is contained in:
Jonas Bonér 2012-02-03 14:55:16 +01:00
parent 7bb49d4a90
commit ec7772b786
4 changed files with 4 additions and 7 deletions

View file

@ -448,14 +448,14 @@ case class RandomRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil,
trait RandomLike { this: RouterConfig
import java.security.SecureRandom
import java.util.Random
def nrOfInstances: Int
def routees: Iterable[String]
private val random = new ThreadLocal[SecureRandom] {
override def initialValue = SecureRandom.getInstance("SHA1PRNG")
private val random = new ThreadLocal[Random] {
override def initialValue = new Random
}
def createRoute(props: Props, routeeProvider: RouteeProvider): Route = {

View file

@ -7,7 +7,6 @@ import akka.pattern.ask
object DirectRoutedRemoteActorMultiJvmSpec extends AbstractRemoteActorMultiJvmSpec {
override def NrOfNodes = 2
// override def PortRangeStart = 3990
class SomeActor extends Actor with Serializable {
def receive = {

View file

@ -8,8 +8,6 @@ import akka.pattern.ask
object NewRemoteActorMultiJvmSpec extends AbstractRemoteActorMultiJvmSpec {
override def NrOfNodes = 2
// override def PortRangeStart = 2990
class SomeActor extends Actor with Serializable {
def receive = {
case "identify" sender ! self

View file

@ -76,7 +76,7 @@ class RandomRoutedRemoteActorMultiJvmNode4 extends AkkaRemoteSpec(RandomRoutedRe
"be locally instantiated on a remote node and be able to communicate through its RemoteActorRef" in {
barrier("start")
val actor = system.actorOf(Props[SomeActor].withRouter(RoundRobinRouter()), "service-hello")
val actor = system.actorOf(Props[SomeActor].withRouter(RandomRouter()), "service-hello")
actor.isInstanceOf[RoutedActorRef] must be(true)
val connectionCount = NrOfNodes - 1