【问题标题】:Erlang: Is there a better way to tell if something is on the stack than regexps on the stacktrace?Erlang:有没有比堆栈跟踪上的正则表达式更好的方法来判断堆栈上是否有东西?
【发布时间】:2011-09-15 18:46:31
【问题描述】:

我正在处理的项目有很多内置的遥测和调试机制,这些机制必须在发布时可用,但系统的大多数部分不得使用。我想构建一个宏,在此类方法的顶部调用,如果没有从非常有限的一组模块中调用该方法,则会引发异常。

例如,我有一个调试模块,可用于从控制台操作系统状态,我有一个 Web 工具,允许管理员检查和更改系统。一些为它们的使用而设计的方法(但在整个系统的模块中实现)对于偶尔使用是很好的,但如果有人错误地将它们作为正常操作的一部分来调用它们,那将是严重的。

编辑:我已经尝试了下面的列表:keysearch 建议,它适用于我可以明确命名的任何模块,这可能是我将要管理的最好的模块。我有 web_foo、web_bar、web_foo_other、web_yippie_ki_yea_mf 等模块来匹配我依赖正则表达式的模块。

我可以执行以下操作。 (我没有编译这个。我希望你给出的任何答案都会阻止我将它投入生产。=]

try
  %gotta do this to get the stacktrace:
  throw(a)
catch
  _ -> 
    Stack = erlang:get_stacktrace(),
    {_, RegExp} = re:compile("webmanager", [multiline]),
    case Match = re:run(Stack, RegExp) of
      nomatch ->
        throw(im_sorry_dave__im_afraid_i_cant_do_that);
      {match, _} ->
        ok
    end
end

【问题讨论】:

  • 从我的小Erlang经验来看,它看起来不像erlang。我认为最好不要使用try-catch。

标签: erlang stack


【解决方案1】:

由于 Stack 是表示方法调用的元组列表,您可以使用lists:keysearch(webmanager, 1, Stack) 检查模块是否在堆栈跟踪中。

【讨论】:

    【解决方案2】:

    根据您的描述,我看不出为什么不将操作支持功能和调试功能隔离在不同的外观模块或进程后面。这些进程代码可以根据其属性限制调用者,例如注册名称(全局、本地、gproc)或节点名称。

    -module(adm_facade).
    -export([register_admin_mode_proc/0,
             unregister_admin_mode_proc/0,
             adm1/1
           ]).
    
    register_admin_mode_proc() ->
        register(admin_mode_proc, self()).
    
    unregister_admin_mode_proc() ->
        unregister(admin_mode_proc).
    
    adm(X) ->
        check_adm(),
        some_other_module:adm(X).
    
    check_adm() ->
        Caller = self(),
        case erlang:whereis(admin_mode_proc) of
            Caller -> ok;
            _ -> erlang:error({access_denied, Caller})
        end.
    

    当然,这会将管理功能限制为单个调用者,但您可以使用 gproc 或您自己的注册器。

    【讨论】:

    • 有问题的方法需要在包含它们检查的数据的特定进程上执行,因此我无法根据进程 ID 限制调用者列表。我也考虑过建立一个消息系统来支持这些特定的调用,但是通信框架(非常非常复数 - 我没有写这个东西)已经失控了,我不需要再添加一个。
    猜你喜欢
    • 2016-01-28
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2017-04-17
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多