Guest User

Untitled

a guest
Feb 21st, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.55 KB | None | 0 0
  1. %%%-------------------------------------------------------------------
  2. %%% File : rdbg.erl
  3. %%% Author : Mats Cronqvist <qthmacr@mwux005>
  4. %%% Description :
  5. %%%
  6. %%% Created : 16 Aug 2004 by Mats Cronqvist <qthmacr@mwux005>
  7. %%%-------------------------------------------------------------------
  8. -module(rdbg).
  9. -export([rdbg/4,rdbg/0]).
  10.  
  11. rdbg(Time,Msgs,Proc,Trc) -> (rdbg())(Time,Msgs,Proc,Trc).
  12.  
  13. rdbg() ->
  14. Pi =
  15. fun(P) when pid(P) ->
  16. case process_info(P, registered_name) of
  17. [] ->
  18. case process_info(P, initial_call) of
  19. {_, {proc_lib,init_p,5}} ->
  20. proc_lib:translate_initial_call(P);
  21. {_,MFA} -> MFA;
  22. undefined -> unknown
  23. end;
  24. {_,Nam} -> Nam;
  25. undefined -> unknown
  26. end;
  27. (P) when port(P) ->
  28. {name,N} = erlang:port_info(P,name),
  29. [Hd|_] = string:tokens(N," "),
  30. Tl = lists:reverse(hd(string:tokens(lists:reverse(Hd),"/"))),
  31. list_to_atom(Tl);
  32. (R) when atom(R) -> R;
  33. ({R,Node}) when atom(R), Node == node() -> R;
  34. ({R, Node}) when atom(R), atom(Node) -> {R, Node}
  35. end,
  36. Ts =
  37. fun(Nw) ->
  38. {_,{H,M,S}} = calendar:now_to_local_time(Nw),
  39. {H,M,S,element(3,Nw)}
  40. end,
  41. Munge =
  42. fun(I) ->
  43. case string:str(I, "Return addr") of
  44. 0 ->
  45. case string:str(I, "cp = ") of
  46. 0 -> [];
  47. _ ->
  48. [_, C|_] = string:tokens(I,"()+"),
  49. list_to_atom(C)
  50. end;
  51. _ ->
  52. case string:str(I, "erminate process normal") of
  53. 0 ->
  54. [_, C|_] = string:tokens(I,"()+"),
  55. list_to_atom(C);
  56. _ -> []
  57. end
  58. end
  59. end,
  60. Stack =
  61. fun(Bin) ->
  62. L = string:tokens(binary_to_list(Bin),"\n"),
  63. {stack,lists:flatten(lists:map(Munge,L))}
  64. end,
  65. Prc =
  66. fun(all) -> all;
  67. (Pd) when pid(Pd) -> Pd;
  68. ({pid,P1,P2}) when integer(P1), integer(P2) -> c:pid(0,P1,P2);
  69. (Reg) when atom(Reg) ->
  70. case whereis(Reg) of
  71. undefined -> exit({rdbg, no_such_process, Reg});
  72. Pid when pid(Pid) -> Pid
  73. end
  74. end,
  75. MsF =
  76. fun(stack, [{Head,Cond,Body}]) ->
  77. [{Head,Cond,[{message,{process_dump}}|Body]}];
  78. (return, [{Head,Cond,Body}]) ->
  79. [{Head,Cond,[{return_trace}|Body]}];
  80. (Head, [{_,Cond,Body}]) when tuple(Head)->
  81. [{Head,Cond,Body}];
  82. (X,_) ->
  83. exit({rdbg,bad_match_spec,X})
  84. end,
  85. Ms =
  86. fun(Mss) -> lists:foldl(MsF, [{'_',[],[]}], Mss) end,
  87. ChkTP =
  88. fun({M,F}) when atom(M), atom(F), M/='_', F/='_' ->
  89. {{M,F,'_'},[],[global]};
  90. ({M,F,MS}) when atom(M), atom(F), M/='_', F/='_' ->
  91. {{M,F,'_'},Ms(MS),[global]};
  92. ({M,F,MS,local}) when atom(M), atom(F), M/='_', F/='_' ->
  93. {{M,F,'_'},Ms(MS),[local]};
  94. ({M,F,MS,global}) when atom(M), atom(F), M/='_', F/='_' ->
  95. {{M,F,'_'},Ms(MS),[global]};
  96. (X) ->
  97. exit({rdbg,unrec_trace_pattern,X})
  98. end,
  99. ChkTPs =
  100. fun(TPs) when list(TPs) -> lists:map(ChkTP,TPs);
  101. (TP) -> [ChkTP(TP)]
  102. end,
  103. SetTPs =
  104. fun({MFA,MS,Fs}) -> erlang:trace_pattern(MFA,MS,Fs) end,
  105. DoInitFun =
  106. fun(Time) ->
  107. erlang:register(rdbg, self()),
  108. erlang:start_timer(Time,self(),{die}),
  109. erlang:trace_pattern({'_','_','_'},false,[local]),
  110. erlang:trace_pattern({'_','_','_'},false,[global])
  111. end,
  112. InitFun =
  113. fun(Time,all,send) -> exit({rdbg,too_many_processes});
  114. (Time,all,'receive') -> exit({rdbg,too_many_processes});
  115. (Time,P, send) ->
  116. DoInitFun(Time),
  117. erlang:trace(Prc(P),true,[send,timestamp]);
  118. (Time,P,'receive') ->
  119. DoInitFun(Time),
  120. erlang:trace(Prc(P),true,['receive',timestamp]);
  121. (Time,P,TPs) ->
  122. CTPs = ChkTPs(TPs),
  123. DoInitFun(Time),
  124. erlang:trace(Prc(P),true,[call,timestamp]),
  125. lists:foreach(SetTPs,CTPs)
  126. end,
  127. LoopFun =
  128. fun(G,N,Out) when N < 1 ->
  129. erlang:trace(all,false,[call,send,'receive']),
  130. erlang:trace_pattern({'_','_','_'},false,[local]),
  131. erlang:trace_pattern({'_','_','_'},false,[global]),
  132. io:fwrite("** rdbg, ~w msgs **~n", [length(Out)]),
  133. io:fwrite("~p~n",[lists:reverse(Out)]),
  134. io:fwrite("~p~n", [process_info(self(),message_queue_len)]);
  135. (G,Cnt,Out) ->
  136. case process_info(self(),message_queue_len) of
  137. {_,N} when N > 100 -> exit({rdbg,msg_queue,N});
  138. _ -> ok
  139. end,
  140. receive
  141. {timeout,_,{die}} ->
  142. G(G,0,Out);
  143. {trace_ts,Pid,send,Msg,To,TS} ->
  144. G(G,Cnt-1,[{send,Ts(TS),Pi(To),Msg}|Out]);
  145. {trace_ts,Pid,'receive',Msg,TS} ->
  146. G(G,Cnt-1,[{'receive',Ts(TS),Msg}|Out]);
  147. {trace_ts,Pid,return_from,MFA,V,TS} ->
  148. G(G,Cnt-1,[{return,MFA,V}|Out]);
  149. {trace_ts,Pid,call,MFA,B,TS} when binary(B) ->
  150. G(G,Cnt-1,[{Pi(Pid),Ts(TS),{Stack(B),MFA}}|Out]);
  151. {trace_ts,Pid,call,MFA,TS} ->
  152. G(G,Cnt-1,[{Pi(Pid),Ts(TS),MFA}|Out])
  153. end
  154. end,
  155. Rdbg =
  156. fun(Time,Msgs,Proc,Trc) when integer(Time), integer(Msgs) ->
  157. Start =
  158. fun() ->InitFun(Time,Proc,Trc),LoopFun(LoopFun,Msgs,[]) end,
  159. erlang:spawn_link(Start)
  160. end.
  161.  
  162. %% Pi = fun(P) when pid(P) -> case process_info(P, registered_name) of [] -> case process_info(P, initial_call) of {_, {proc_lib,init_p,5}} -> proc_lib:translate_initial_call(P); {_,MFA} -> MFA; undefined -> unknown end; {_,Nam} -> Nam; undefined -> unknown end; (P) when port(P) -> {name,N} = erlang:port_info(P,name), [Hd|_] = string:tokens(N," "), Tl = lists:reverse(hd(string:tokens(lists:reverse(Hd),"/"))), list_to_atom(Tl); (R) when atom(R) -> R; ({R,Node}) when atom(R), Node == node() -> R; ({R, Node}) when atom(R), atom(Node) -> {R, Node} end, Ts = fun(Nw) -> {_,{H,M,S}} = calendar:now_to_local_time(Nw), {H,M,S,element(3,Nw)} end, Munge = fun(I) -> case string:str(I, "Return addr") of 0 -> case string:str(I, "cp = ") of 0 -> []; _ -> [_, C|_] = string:tokens(I,"()+"), list_to_atom(C) end; _ -> case string:str(I, "erminate process normal") of 0 -> [_, C|_] = string:tokens(I,"()+"), list_to_atom(C); _ -> [] end end end, Stack = fun(Bin) -> L = string:tokens(binary_to_list(Bin),"\n"), {stack,lists:flatten(lists:map(Munge,L))} end, Prc = fun(all) -> all; (Pd) when pid(Pd) -> Pd; ({pid,P1,P2}) when integer(P1), integer(P2) -> c:pid(0,P1,P2); (Reg) when atom(Reg) -> case whereis(Reg) of undefined -> exit({rdbg, no_such_process, Reg}); Pid when pid(Pid) -> Pid end end, MsF = fun(stack, [{Head,Cond,Body}]) -> [{Head,Cond,[{message,{process_dump}}|Body]}]; (return, [{Head,Cond,Body}]) -> [{Head,Cond,[{return_trace}|Body]}]; (Head, [{_,Cond,Body}]) when tuple(Head)-> [{Head,Cond,Body}]; (X,_) -> exit({rdbg,bad_match_spec,X}) end, Ms = fun(Mss) -> lists:foldl(MsF, [{'_',[],[]}], Mss) end, ChkTP = fun({M,F}) when atom(M), atom(F), M/='_', F/='_' -> {{M,F,'_'},[],[global]}; ({M,F,MS}) when atom(M), atom(F), M/='_', F/='_' -> {{M,F,'_'},Ms(MS),[global]}; ({M,F,MS,local}) when atom(M), atom(F), M/='_', F/='_' -> {{M,F,'_'},Ms(MS),[local]}; ({M,F,MS,global}) when atom(M), atom(F), M/='_', F/='_' -> {{M,F,'_'},Ms(MS),[global]}; (X) -> exit({rdbg,unrec_trace_pattern,X}) end, ChkTPs = fun(TPs) when list(TPs) -> lists:map(ChkTP,TPs); (TP) -> [ChkTP(TP)] end, SetTPs = fun({MFA,MS,Fs}) -> erlang:trace_pattern(MFA,MS,Fs) end, DoInitFun = fun(Time) -> erlang:register(rdbg, self()), erlang:start_timer(Time,self(),{die}), erlang:trace_pattern({'_','_','_'},false,[local]), erlang:trace_pattern({'_','_','_'},false,[global]) end, InitFun = fun(Time,all,send) -> exit({rdbg,too_many_processes}); (Time,all,'receive') -> exit({rdbg,too_many_processes}); (Time,P, send) -> DoInitFun(Time), erlang:trace(Prc(P),true,[send,timestamp]); (Time,P,'receive') -> DoInitFun(Time), erlang:trace(Prc(P),true,['receive',timestamp]); (Time,P,TPs) -> CTPs = ChkTPs(TPs), DoInitFun(Time), erlang:trace(Prc(P),true,[call,timestamp]), lists:foreach(SetTPs,CTPs) end, LoopFun = fun(G,N,Out) when N < 1 -> erlang:trace(all,false,[call,send,'receive']), erlang:trace_pattern({'_','_','_'},false,[local]), erlang:trace_pattern({'_','_','_'},false,[global]), io:fwrite("** rdbg, ~w msgs **~n", [length(Out)]), io:fwrite("~p~n",[lists:reverse(Out)]), io:fwrite("~p~n", [process_info(self(),message_queue_len)]); (G,Cnt,Out) -> case process_info(self(),message_queue_len) of {_,N} when N > 100 -> exit({rdbg,msg_queue,N}); _ -> ok end, receive {timeout,_,{die}} -> G(G,0,Out); {trace_ts,Pid,send,Msg,To,TS} -> G(G,Cnt-1,[{send,Ts(TS),Pi(To),Msg}|Out]); {trace_ts,Pid,'receive',Msg,TS} -> G(G,Cnt-1,[{'receive',Ts(TS),Msg}|Out]); {trace_ts,Pid,return_from,MFA,V,TS} -> G(G,Cnt-1,[{return,MFA,V}|Out]); {trace_ts,Pid,call,MFA,B,TS} when binary(B) -> G(G,Cnt-1,[{Pi(Pid),Ts(TS),{Stack(B),MFA}}|Out]); {trace_ts,Pid,call,MFA,TS} -> G(G,Cnt-1,[{Pi(Pid),Ts(TS),MFA}|Out]) end end, Rdbg = fun(Time,Msgs,Proc,Trc) when integer(Time), integer(Msgs) -> Start = fun() -> InitFun(Time,Proc,Trc),LoopFun(LoopFun,Msgs,[]) end, erlang:spawn_link(Start) end.
Add Comment
Please, Sign In to add comment