簡體   English   中英

Elixir 堆棧跟蹤是否包括每個輸入的 function?

[英]Do Elixir stacktraces include every entered function?

我正在處理Postgrex中的一個問題,這是一個 Elixir Postgres 驅動程序。

但是,我對下面的堆棧跟蹤感到困惑。 (為了使其可讀,我只刪除了冗長的 arguments 到msg_recv/4 。)

16:52:54.323 [error] GenServer #PID<0.234.0> terminating
** (FunctionClauseError) no function clause matching in Postgrex.Protocol.msg_recv/4
    (postgrex 0.15.5) lib/postgrex/protocol.ex:2837: Postgrex.Protocol.msg_recv(...SNIP)
    (postgrex 0.15.5) lib/postgrex/protocol.ex:816: Postgrex.Protocol.bootstrap_recv/4
    (postgrex 0.15.5) lib/postgrex/protocol.ex:579: Postgrex.Protocol.handshake/2
    (db_connection 2.1.0) lib/db_connection/connection.ex:69: DBConnection.Connection.connect/2
    (connection 1.0.4) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol

堆棧跟蹤似乎表明handshake/2調用bootstrap_recv/4 ,但在handshake/2中沒有直接調用bootstrap_recv/4

第 579 行確實在handshake/2內部,並且是對do_handshake/2的調用,其中有兩個變體,它們本身稱為ssl/2startup/2

我找不到在此代碼路徑中調用bootstrap_recv/4的位置。

為什么do_handshake/2ssl/2startup/2之一(以及任何其他后續調用導致bootstrap_recv/4並最終導致msg_recv/4 )不在堆棧跟蹤中?

據推測,我誤解了 Elixir 堆棧跟蹤。

編輯:針對一般問題提出如此詳細的問題是一種恥辱,但我會留下這個問題,以防有人通過調試遇到這種情況。

不,由於 Erlang VM,Elixir 中的堆棧跟蹤不包含每個輸入的 function。 我在 Elixir 論壇的帖子中發現了這一點。 GitHub 問題中也提到了它。

erlang-questions郵件列表中,Joe Armstrong 提到 Erlang 將其稱為“ 最后調用優化”,並給出了解釋。

下面的代碼用幾行簡單的代碼來防止尾調用演示了不同之處。

defmodule Demo do
  def first() do
    second()

    # Uncomment to prevent tail-call, and `first` appears in the stacktrace.
    # case second() do
    #   _ -> {:ok, 0}
    # end
  end

  # Elixir knows third() is still a tail-call.
  def second() do
    r = third()
    _ = 1 + 1
    # dummy() # Uncomment to prevent tail-call, and `second` appears in the stacktrace.
    r
  end

  def third() do
    IO.inspect(Process.info(self(), :current_stacktrace))
    {:ok, 0}
  end

  defp dummy, do: nil
end

IO.inspect(Demo.first)

堆棧跟蹤結果:

{:current_stacktrace,
 [
   {Process, :info, 2, [file: 'lib/process.ex', line: 765]},
   {Demo, :third, 0, [file: 'demo.exs', line: 21]},
   {:elixir_compiler_0, :__FILE__, 1, [file: 'demo.exs', line: 30]},
   {:elixir_compiler, :dispatch, 4, [file: 'src/elixir_compiler.erl', line: 75]},
   {:elixir_compiler, :compile, 3, [file: 'src/elixir_compiler.erl', line: 60]},
   {:elixir_lexical, :run, 3, [file: 'src/elixir_lexical.erl', line: 15]},
   {:elixir_compiler, :quoted, 3, [file: 'src/elixir_compiler.erl', line: 18]}
 ]}
{:ok, 0}

在同一代碼中調整注釋行(如前所述)時會產生堆棧跟蹤:

{:current_stacktrace,
 [
   {Process, :info, 2, [file: 'lib/process.ex', line: 765]},
   {Demo, :third, 0, [file: 'demo.exs', line: 20]},
   {Demo, :second, 0, [file: 'demo.exs', line: 13]},
   {Demo, :first, 0, [file: 'demo.exs', line: 6]},
   {:elixir_compiler_0, :__FILE__, 1, [file: 'demo.exs', line: 29]},
   {:elixir_compiler, :dispatch, 4, [file: 'src/elixir_compiler.erl', line: 75]},
   {:elixir_compiler, :compile, 3, [file: 'src/elixir_compiler.erl', line: 60]}
 ]}
{:ok, 0}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM