Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: Scala 2.7.4
    • Component/s: Misc Library
    • Labels:
      None
    • Environment:

      actors, leak

      Description

      Code to reproduce the leak:

      import scala.actors.Actor._

      object Test {

      val rt = Runtime.getRuntime()

      val sender = actor {
      while(true)

      { receiver ! new Array[Int] (1048576) System.gc() println ("Used Mem: " + (((rt.totalMemory() - rt.freeMemory()) / 1048576.) formatted "%.2f") + " Mb") }

      }

      val receiver = actor {
      loop {
      react

      { case x: Array[Int] => println ("received ["+x.length+"]") }

      }
      }

      def main (args: Array[String])

      { sender }

      }

      I does not leak with receive instead of react.
      It happens only when sending from another Actor, as was mentioned on mailing list.

      Does not leak commenting FJTaskRunner stuff in scala.actors.Scheduler.execute and leaving only
      sched execute

      { fun }

      Calling FJTaskRunner.put instead of .push reduces leak gradually but it's still there.
      Same happens when calling take() instead of get() in FJTaskRunner.confirmTake, but there is comment why it should not be done.

      Anyway, direct calling FJTaskRunner.push from Scheduler.execute seems like a hack, since it is declared "/protected/ public" - it seems it was originally protected and was not supposed to be called from outside.

      I can't figure out why is still leaks even with FJTaskRunner.take instead of get, but anyway I see this as potential problem, since VolatileTaskRef is only cleaned in checkOverflow() method which is very rarely called, if ever.

      I think the safe way is to leave FJTaskRunner.push as protected, never call it, use only "sched execute { fun }

      ", but I am not sure.

        Activity

        Hide
        Alex Yakovlev added a comment -

        One more thing I suggest is to add in the end of scala.actors.Reaction.run()

        this.a = null
        this.f = null
        this.msg = null

        Thus even if FJTaskRunner will hold 'leaked' references to FJTask and Reaction, it will hold no references to user's (huge) data. This can happen if we create a lot of actors that will fill FJTaskRunner's array of VolatileTaskRef that are not nulled because of get() instead of take()

        Show
        Alex Yakovlev added a comment - One more thing I suggest is to add in the end of scala.actors.Reaction.run() this.a = null this.f = null this.msg = null Thus even if FJTaskRunner will hold 'leaked' references to FJTask and Reaction, it will hold no references to user's (huge) data. This can happen if we create a lot of actors that will fill FJTaskRunner's array of VolatileTaskRef that are not nulled because of get() instead of take()
        Hide
        Philipp Haller added a comment -

        Fixed in r17380 (trunk) and r17381 (2.7.x).

        Show
        Philipp Haller added a comment - Fixed in r17380 (trunk) and r17381 (2.7.x).
        Hide
        Philipp Haller added a comment -

        (In r19988) Moved non-deterministic test for see SI-1801 to pending.

        Show
        Philipp Haller added a comment - (In r19988) Moved non-deterministic test for see SI-1801 to pending.

          People

          • Assignee:
            Philipp Haller
            Reporter:
            Alex Yakovlev
            TracCC:
            Erik Engbrecht, Michael Nascimento Santos
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development