[Erlang 0076] Erlang Shell一个怪问题

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

 

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

 

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

 

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 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). 
 
运行上面的代码t:b(),发送消息,然后查看进程状态,$$$$~~~~~~,看到了没有,这种写法消息队列里面是可以看到积压的消息的!! 那么之前的写法,接收到的消息在哪里呢?

 

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,[]}]

 

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

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一个怪问题