You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Mojolicious中获取准确的caller()及物理源码堆栈跟踪?

Mojolicious中获取准确caller()信息的解决方法

问题场景

在Mojolicious::Lite应用中使用caller(0)获取调用信息时,返回的文件路径、行号并非实际源码位置,不符合预期:

示例代码(/foo/bar/app.pl)

#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $c = shift;

  my ($package, $filename, $line, $subroutine, $hasargs, $wantarray,
    $evaltext, $is_require, $hints, $bitmask, $hinthash) = caller(0);

  $c->render(text =>
    'p=' . $package    . ',' .
    'f=' . $filename   . ',' .
    'l=' . $line       . ',' .
    'm=' . $subroutine
  );
};

app->start;

实际输出

  • 用/foo/bar/app.pl daemon启动:
p=Mojolicious,f=/usr/local/share/perl5/Mojolicious.pm,l=202,m=main::__ANON__
  • 用morbo /foo/bar/app.pl启动:
p=Mojolicious,f=/usr/local/share/perl5/Mojolicious.pm,l=202,m=Mojo::Server::Sandbox::b89e17a47746799cd9250564e1c58531::__ANON__

期望输出

f=/foo/bar/app.pl
l=7
m=main::__ANON__

解决方法

1. 遍历调用栈定位目标帧

Mojolicious会内部包装路由回调,caller(0)指向框架内部调用点,需遍历栈帧找到匹配源码文件的条目:

get '/' => sub {
  my $c = shift;

  my ($package, $filename, $line, $subroutine);
  my $level = 0;
  while (1) {
    ($package, $filename, $line, $subroutine) = caller($level++);
    last unless defined $filename;
    # 匹配你的应用文件路径
    last if $filename eq '/foo/bar/app.pl';
  }

  $c->render(text =>
    'f=' . $filename   . "\n" .
    'l=' . $line       . "\n" .
    'm=' . $subroutine
  );
};

2. 适配morbo沙箱模式

morbo会将代码加载到沙箱包中,子例程名带沙箱前缀,可通过正则修正:

get '/' => sub {
  my $c = shift;

  my ($package, $filename, $line, $subroutine);
  my $level = 0;
  while (1) {
    ($package, $filename, $line, $subroutine) = caller($level++);
    last unless defined $filename;
    last if $filename eq '/foo/bar/app.pl';
  }
  # 替换沙箱子例程名为原始格式
  $subroutine = 'main::__ANON__' if $subroutine =~ /::__ANON__$/;

  $c->render(text =>
    'f=' . $filename   . "\n" .
    'l=' . $line       . "\n" .
    'm=' . $subroutine
  );
};

原理说明

Mojolicious的路由回调由框架调度逻辑触发,caller(0)返回的是框架内部的调用位置。通过遍历调用栈跳过框架内部帧,即可定位到回调函数实际定义的源码帧,获取正确的文件路径、行号和子例程信息。

内容的提问来源于stack exchange,提问作者mvanle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:53:26