[Erlang 0076] Erlang Shell一个怪问题

时间:2022-10-26 21:49:07

   最近一直在忙,偶尔有点时间在读书,补充一下能量;最近在学习 程序设计语言-实践之路 非常感慨,之前误打误撞的一点所得原来有一个更系统,完整的知识体系;于是沉下心来,慢慢吸收.像北上广这样的城市快速的代谢着我们的精力和知识,不容懈怠,不过倒也不必急躁,如果心浮气躁,效果必然大打折扣;抽时间整理一下最近的笔记,先从一个怪异的问题开始吧!

 

  在Erlang shell中我常常创建一个无限等待接收消息的进程来做一些测试,代码:spawn(fun() -> receive after infinity-> io:format("DONE!") end end).问题复现步骤:1.在Erlang Shell中启动这个进程之后 2.向该进程发送消息 3.由于没有消息提取的逻辑,该进程收到的消息就会积压在消息队列里面,可以通过erlang:process_info查看;首先使用Shell进程来试一下,可以看到结果是和我们的预期一致的:

 

 

[Erlang 0076] Erlang Shell一个怪问题
23> [self()!abc || _<-lists:seq(1,20)].
[abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,
abc,abc,abc,abc,abc,abc]
24> erlang:process_info(self()).
[{current_function,{erl_eval,do_apply,
6}},
{initial_call,{erlang,apply,
2}},
{status,running},
{message_queue_len,
20},
{messages,[abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,
abc,abc,abc,abc,abc,abc,abc,abc]},
{links,[<
0.26.0>]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<
0.25.0>},
{total_heap_size,
5168},
{heap_size,
2584},
{stack_size,
24},
{reductions,
68319},
{garbage_collection,[{min_bin_vheap_size,
46368},
{min_heap_size,
233},
{fullsweep_after,
65535},
{minor_gcs,
16}]},
{suspending,[]}]
[Erlang 0076] Erlang Shell一个怪问题
   下面我们使用spawn(fun)的方式试一下,看下面的结果,在发送了两条消息之后查看进程状态,发现消息队列是空的!!!

 

[Erlang 0076] Erlang Shell一个怪问题
Erlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.
9 (abort with ^G)
1> P=spawn(fun() -> receive after infinity-> io:format("dONE!") end end).
<
0.34.0>
2> P!abc.
abc
3> P!abcd.
abcd
4> erlang:process_info(P).
[{current_function,{erl_eval,receive_clauses,
8}},
{initial_call,{erlang,apply,
2}},
{status,waiting},
{message_queue_len,
0},
{messages,[]},
{links,[]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<
0.25.0>},
{total_heap_size,
233},
{heap_size,
233},
{stack_size,
10},
{reductions,
26},
{garbage_collection,[{min_bin_vheap_size,
46368},
{min_heap_size,
233},
{fullsweep_after,
65535},
{minor_gcs,
0}]},
{suspending,[]}]
[Erlang 0076] Erlang Shell一个怪问题

 

   难道是这样的写法在Erlang Shell中有问题?我就把这段代码放在一个测试模块中试一下: [Erlang 0076] Erlang Shell一个怪问题
-module(t).
-compile(export_all).

a() ->
receive
{Data}->
io:format("reveive Data :~p~n ",[Data]),
a()
after infinity ->
io:format("Done!")
end.

b() -> spawn(fun() -> receive after infinity->
io:format("dONE!") end end).
[Erlang 0076] Erlang Shell一个怪问题
 运行上面的代码t:b(),发送消息,然后查看进程状态,$$$$~~~~~~,看到了没有,这种写法消息队列里面是可以看到积压的消息的!! 那么之前的写法,接收到的消息在哪里呢?

 

[Erlang 0076] Erlang Shell一个怪问题
5> t:b().
<
0.39.0>
6> v(5)!abc.
abc
7> v(5)!abcd.
abcd
8> erlang:process_info(v(5)).
[{current_function,{t,
'-b/0-fun-0-',0}},
{initial_call,{erlang,apply,
2}},
{status,waiting},
{message_queue_len,
2},
{messages,[abc,abcd]},
{links,[]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<
0.25.0>},
{total_heap_size,
233},
{heap_size,
233},
{stack_size,
0},
{reductions,
2},
{garbage_collection,[{min_bin_vheap_size,
46368},
{min_heap_size,
233},
{fullsweep_after,
65535},
{minor_gcs,
0}]},
{suspending,[]}]
[Erlang 0076] Erlang Shell一个怪问题

 

   消息有可能在哪里呢?还有一个办法,我们把stacktrace输出一下,从下面的结果中我们可以看到一点端倪:进程P的堆栈信息中y(2) [abcd,abc]就是之前我们香它发送的消息;查看一下t:b()进程,并没有看到类似的信息;通过对比,突破点应该在这里,但是苦于没有找到process_dsiplay输出信息的详细说明,难以继续了,记录于此,日后继续

[Erlang 0076] Erlang Shell一个怪问题
9> bt(P).
Program
counter: 0x00007f738b7d76c0 (erl_eval:receive_clauses/8 + 168)
CP: 0x0000000000000000 (invalid)
arity =
0

0x00007f738d11c2d0 Return addr 0x000000000084e1b8 (<terminate process normally>)
y(
0) []
y(
1) value
y(
2) [abcd,abc]
y(
3) {value,#Fun<shell.7.20862592>}
y(
4) {eval,#Fun<shell.24.20862592>}
y(
5) []
y(
6) {[{call,1,{remote,1,{atom,1,io},{atom,1,format}},[{string,1,"dONE!"}]}],[]}
y(
7) []
y(
8) infinity
ok
10> bt(v(5)).
Program
counter: 0x00007f73852f7ec0 (t:'-b/0-fun-0-'/0 + 8)
CP: 0x000000000084e1b8 (<terminate process normally>)
arity =
0
ok
11>

[Erlang 0076] Erlang Shell一个怪问题

 

最后贴张图,今年银河印象的作品 车手

[Erlang 0076] Erlang Shell一个怪问题