www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 16106] New: Calling a fiber from itself causes hard-to-debug

https://issues.dlang.org/show_bug.cgi?id=16106

          Issue ID: 16106
           Summary: Calling a fiber from itself causes hard-to-debug stack
                    corruption
           Product: D
           Version: D2
          Hardware: x86_64
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: druntime
          Assignee: nobody puremagic.com
          Reporter: clugdbug yahoo.com.au

If you are in fiber `f`, and you call `f.call()`, then you are switching the
context to yourself.
There is an `in` contract in Fiber.call() which is meant to prevent this:
assert( m_state == State.HOLD );

That assert will fail, because the fiber is running. But if contracts are
disabled, then execution will continue anyway.

Conceptually, switching context to yourself is a no-op. The function could
simply return. I'm not sure that would be a good idea, but it's certainly
possible. And it *almost* behaves that way. The function fiber_switchContext()
pushes the registers onto the existing stack, then pops them from the new
stack.
In this case, the old stack and new stack are the same. Except that the new
stack pointer is the top of the new stack *before the pushes were made*.

So, it loads the registers from the completely wrong place. If you're lucky,
you get a segfault. If you don't, you'll end up in a completely unrelated
place. Either way it is quite difficult to diagnose why it has happened.

Admittedly, this only happens after an 'in' contract violation. But I think we
should do something a bit more robust.

The check for ``m_state == State.HOLD`` is not expensive (one CMP and a
predictable branch). It should be moved out of the contract into the function
body. The consequences of a totally corrupt stack are _extremely_ severe. It's
worth sacrificing a single clock cycle to prevent this debugging nightmare.

--
May 31 2016