Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parts of fiber stack frames are leaked under certain circumstances #282

Closed
exFalso opened this issue Jul 7, 2017 · 2 comments
Closed

Parts of fiber stack frames are leaked under certain circumstances #282

exFalso opened this issue Jul 7, 2017 · 2 comments
Assignees
Labels

Comments

@exFalso
Copy link
Contributor

exFalso commented Jul 7, 2017

If a function has two subsequent variable scopes with variables of different types then asm cannot infer whether the stack slots refer to references or not, thereby causing quasar instrumentation to omit incrementing either of idxObj or idxPrim in the InstrumentMethod.FrameInfo constructor. This causes the slots number in the frame record to be smaller than it should be, causing Stack.popMethod to leak references (if there are more objects in the function than primitives).

To reproduce:

import co.paralleluniverse.fibers.Fiber
import co.paralleluniverse.fibers.Stack
import co.paralleluniverse.fibers.Suspendable
import java.util.concurrent.TimeUnit

class MyFiber : Fiber<Unit>() {
    @Suspendable
    override fun run() {
        leaky()

        val stackField = Fiber::class.java.getDeclaredField("stack")
        stackField.isAccessible = true
        val objectsField = Stack::class.java.getDeclaredField("dataObject")
        objectsField.isAccessible = true
        val stack = objectsField.get(stackField.get(this)) as Array<Any?>
        println(stack.toList().take(10)) // prints nulls as well as "leaked"
    }

    @Suspendable
    fun leaky() {
        val a = object {} // this is so that we have more objects than primitives
        do {
            val leaked = "leaked"
            Fiber.park(1, TimeUnit.NANOSECONDS)
        } while (false)
        do {
            val primitive = 2
            Fiber.park(1, TimeUnit.NANOSECONDS)
        } while (false)
    }
}

fun main(args: Array<String>) {
    MyFiber().start()
}
@pron
Copy link
Contributor

pron commented Jul 24, 2017

The cause is that we clear the references on the stack in Stack.popMethod, but the number of slots to clear is taken from the current frame, which may not be the only frame in the method.

@pron
Copy link
Contributor

pron commented Jul 24, 2017

Fixed in 977edd2
You can try it in 0.7.9-SNAPSHOT

@pron pron closed this as completed Jul 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants