产卵Goroutines时恢复呼叫堆栈

发布于 2025-02-05 11:23:27 字数 1027 浏览 2 评论 0 原文

以下

func a() { b() }
func b() { c() }
func c() { d() }
func d() {
    pc := make([]uintptr, 10)
    n := runtime.Callers(1, pc)
    if n == 0 {
        return
    }

    frames := runtime.CallersFrames(pc[:n])

    for {
        frame, more := frames.Next()

        fmt.Println(frame.Function)

        if !more {
            break
        }
    }

}

func main() {
    a()
    // The reason for this sleep will become apparent in an incoming example
    // where we spawn a goroutine and do not explicitely wait for it to finish
    time.Sleep(time.Second)
}

输出

main.d
main.c
main.b
main.a
main.main
runtime.main
runtime.goexit

我预期的 单独的goroutine中调用功能的情况

func b() { go c() }

。我面临着一个函数 c 在这样的CAS中的

main.d
main.c
runtime.goexit

,而我希望它能与上述相同。

有解决这个问题的解决方案吗?也许可以捕获呼叫堆栈并将其传递给功能 d 的东西?请注意,性能将很重要,我希望避免事先处理堆栈,如我的真实生活示例中, d 可能或可能不需要触发对Runtime.Callers的调用。

The following

func a() { b() }
func b() { c() }
func c() { d() }
func d() {
    pc := make([]uintptr, 10)
    n := runtime.Callers(1, pc)
    if n == 0 {
        return
    }

    frames := runtime.CallersFrames(pc[:n])

    for {
        frame, more := frames.Next()

        fmt.Println(frame.Function)

        if !more {
            break
        }
    }

}

func main() {
    a()
    // The reason for this sleep will become apparent in an incoming example
    // where we spawn a goroutine and do not explicitely wait for it to finish
    time.Sleep(time.Second)
}

outputs

main.d
main.c
main.b
main.a
main.main
runtime.main
runtime.goexit

as I expected. I am facing a situation where function c is called in a separate goroutine

func b() { go c() }

In such cas it outputs

main.d
main.c
runtime.goexit

, while I wished it to outpout the same as above.

Is there a solution to this problem? Maybe something to capture a call stack and pass it to function d? Note that performance will matter and I wish to avoid processing the stack beforehand as in my real life example, d might or might not need to trigger the call to runtime.Callers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

第几種人 2025-02-12 11:23:28

没有解决方案。当您启动作为另一个Goroutine的函数时,它将完全独立于启动Goroutine运行。发射器可能会继续或完全完成 /终止。出于明显的原因,“开始”堆栈没有保留。

因此,除非您在启动另一个Goroutine时明确查询并保留 /通过堆栈,否则您会丢失它。

注意:可以检测一个函数是否作为goroutine启动,并且您只能在这种情况下限制查询和保留堆栈,而在所有情况下都不能限制和保留堆栈。有关详细信息,请参见

There is no solution. When you launch a function as another goroutine, it will run completely independent from the launching goroutine. The launcher may move on or completely finish / terminate. The "starting" stack is not retained for obvious reasons.

So unless you explicitly query and retain / pass the stack yourself when launching another goroutine, you'll lose it.

Note: it's possible to detect if a function is launched as a goroutine or not, and you could limit querying and retaining the stack only if so, and not in all cases. For details, see Check if function is being called as goroutine or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文