digitalmars.D.bugs - [Issue 16106] New: Calling a fiber from itself causes hard-to-debug
- via Digitalmars-d-bugs (37/37) May 31 2016 https://issues.dlang.org/show_bug.cgi?id=16106
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