Erlang 生成问题
我在 erlang 中遇到了“spawn”问题,似乎进程在一段时间后就死掉了。这是简单的代码:
-module(simple).
-export([server/1, client/1, owner/1, spawn_n/2, start/1, main/1]).
server(State) ->
receive
{request,Return_PID} ->
io:format("SERVER ~w: Client request recieved from ~w~n", [self(),Return_PID]),
NewState = State + 1,
Return_PID ! {hit_count,NewState},
server(NewState);
{server_owner,Owner_PID} ->
io:format("SERVER ~w: Owner request recieved from ~w~n", [self(), Owner_PID]),
Owner_PID ! {hit_count,State},
server(State);
reset ->
io:format("SERVER ~w: State reset to zero.~n", [self()]),
server(0)
end.
client(Server_Address) ->
Server_Address ! {request, self()},
receive
{hit_count,Number} ->
io:format("CLIENT ~w: Hit count was ~w~n", [self(),Number])
end.
owner(Server_PID) ->
timer:sleep(random:uniform(100)),
Server_PID ! {server_owner,self()},
receive
{hit_count,Number} when Number > 5 ->
io:format("OWNER: Hit count is ~w , reseting counter. ~n", [Number]),
Server_PID ! reset,
owner(Server_PID);
{hit_count,Number} when Number < 5 ->
io:format("OWNER ~w: Hit count was ~w~n", [self(), Number]),
owner(Server_PID)
end.
spawn_n(N, Server_PID) ->
if
N>0 ->
spawn(simple,client,[Server_PID]),
timer:sleep(random:uniform(100)),
spawn_n(N-1,Server_PID);
N==0 ->
io:format("Last client spawned. ~n")
end.
start(N) ->
Server_PID = spawn(simple,server,[0]),
spawn(simple,owner,[Server_PID]),
spawn(simple,spawn_n,[N,Server_PID]).
main([Arg]) ->
N = list_to_integer(atom_to_list(Arg)),
start(N),
init:stop().
这是我运行它时得到的示例:
erl -noshell -s simple main 20
SERVER <0.28.0>: Client request recieved from <0.31.0>
CLIENT <0.31.0>: Hit count was 1
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.32.0>
OWNER <0.29.0>: Hit count was 1
CLIENT <0.32.0>: Hit count was 2
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.33.0>
OWNER <0.29.0>: Hit count was 2
CLIENT <0.33.0>: Hit count was 3
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.34.0>
OWNER <0.29.0>: Hit count was 3
CLIENT <0.34.0>: Hit count was 4
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.35.0>
OWNER <0.29.0>: Hit count was 4
CLIENT <0.35.0>: Hit count was 5
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.36.0>
CLIENT <0.36.0>: Hit count was 6
SERVER <0.28.0>: Client request recieved from <0.37.0>
CLIENT <0.37.0>: Hit count was 7
SERVER <0.28.0>: Client request recieved from <0.38.0>
CLIENT <0.38.0>: Hit count was 8
SERVER <0.28.0>: Client request recieved from <0.39.0>
CLIENT <0.39.0>: Hit count was 9
SERVER <0.28.0>: Client request recieved from <0.40.0>
CLIENT <0.40.0>: Hit count was 10
SERVER <0.28.0>: Client request recieved from <0.41.0>
CLIENT <0.41.0>: Hit count was 11
SERVER <0.28.0>: Client request recieved from <0.42.0>
CLIENT <0.42.0>: Hit count was 12
SERVER <0.28.0>: Client request recieved from <0.43.0>
CLIENT <0.43.0>: Hit count was 13
SERVER <0.28.0>: Client request recieved from <0.44.0>
CLIENT <0.44.0>: Hit count was 14
SERVER <0.28.0>: Client request recieved from <0.45.0>
CLIENT <0.45.0>: Hit count was 15
SERVER <0.28.0>: Client request recieved from <0.46.0>
CLIENT <0.46.0>: Hit count was 16
SERVER <0.28.0>: Client request recieved from <0.47.0>
CLIENT <0.47.0>: Hit count was 17
SERVER <0.28.0>: Client request recieved from <0.48.0>
CLIENT <0.48.0>: Hit count was 18
{error_logger,{{2011,6,27},{12,57,8}},"~s~n",["Error in process <0.28.0> with ex
it value: {terminated,[{io,format,[<0.22.0>,\"SERVER ~w: Client request recieved
from ~w~n\",[<0.28.0>,<0.49.0>]]},{simple,server,1}]}\n"]}
我不明白。进程就死掉了还是怎么的?它不应该终止! 我正在 Windows 7 上运行,如果它可能与 Windows 相关的话。
谢谢
编辑:这就是执行 application:start(sasl) 时发生的情况。前:
C:\Program Files\erl5.8.4\bin>erl
Eshell V5.8.4 (abort with ^G)
1> application:start(sasl).
ok
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.37.0>},
{name,alarm_handler},
{mfargs,{alarm_handler,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.38.0>},
{name,overload},
{mfargs,{overload,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_sup}
started: [{pid,<0.36.0>},
{name,sasl_safe_sup},
{mfargs,
{supervisor,start_link,
[{local,sasl_safe_sup},sasl,safe
{restart_type,permanent},
{shutdown,infinity},
{child_type,supervisor}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_sup}
started: [{pid,<0.39.0>},
{name,release_handler},
{mfargs,{release_handler,start_link,[]}}
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
application: sasl
started_at: nonode@nohost
2> simple:main(['20']).
ok
SERVER <0.42.0>: Client request recieved from <0.45.0>
3> CLIENT <0.45.0>: Hit count was 1
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.47.0>
3> OWNER <0.43.0>: Hit count was 1
3> CLIENT <0.47.0>: Hit count was 2
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.48.0>
3> OWNER <0.43.0>: Hit count was 2
3> CLIENT <0.48.0>: Hit count was 3
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.49.0>
3> OWNER <0.43.0>: Hit count was 3
3> CLIENT <0.49.0>: Hit count was 4
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.50.0>
3> OWNER <0.43.0>: Hit count was 4
3> CLIENT <0.50.0>: Hit count was 5
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.51.0>
3> CLIENT <0.51.0>: Hit count was 6
3> SERVER <0.42.0>: Client request recieved from <0.52.0>
3> CLIENT <0.52.0>: Hit count was 7
3> SERVER <0.42.0>: Client request recieved from <0.53.0>
3> CLIENT <0.53.0>: Hit count was 8
3> SERVER <0.42.0>: Client request recieved from <0.54.0>
3> CLIENT <0.54.0>: Hit count was 9
3> SERVER <0.42.0>: Client request recieved from <0.55.0>
3> CLIENT <0.55.0>: Hit count was 10
3> SERVER <0.42.0>: Client request recieved from <0.56.0>
3> CLIENT <0.56.0>: Hit count was 11
3> SERVER <0.42.0>: Client request recieved from <0.57.0>
3> CLIENT <0.57.0>: Hit count was 12
3> SERVER <0.42.0>: Client request recieved from <0.58.0>
3> CLIENT <0.58.0>: Hit count was 13
3> SERVER <0.42.0>: Client request recieved from <0.59.0>
3> CLIENT <0.59.0>: Hit count was 14
3> SERVER <0.42.0>: Client request recieved from <0.60.0>
3> CLIENT <0.60.0>: Hit count was 15
3> SERVER <0.42.0>: Client request recieved from <0.61.0>
3> CLIENT <0.61.0>: Hit count was 16
3> SERVER <0.42.0>: Client request recieved from <0.62.0>
3> CLIENT <0.62.0>: Hit count was 17
3> SERVER <0.42.0>: Client request recieved from <0.63.0>
3> CLIENT <0.63.0>: Hit count was 18
3> {error_logger,{{2011,6,27},{16,3,58}},"~s~n",["Error in proc
exit value: {terminated,[{io,format,[<0.23.0>,\"SERVER ~w: Cli
ved from ~w~n\",[<0.42.0>,<0.64.0>]]},{simple,server,1}]}\n"]}
I am having problem with 'spawn' in erlang, it seems processes just die after awhile. Here's the simple code:
-module(simple).
-export([server/1, client/1, owner/1, spawn_n/2, start/1, main/1]).
server(State) ->
receive
{request,Return_PID} ->
io:format("SERVER ~w: Client request recieved from ~w~n", [self(),Return_PID]),
NewState = State + 1,
Return_PID ! {hit_count,NewState},
server(NewState);
{server_owner,Owner_PID} ->
io:format("SERVER ~w: Owner request recieved from ~w~n", [self(), Owner_PID]),
Owner_PID ! {hit_count,State},
server(State);
reset ->
io:format("SERVER ~w: State reset to zero.~n", [self()]),
server(0)
end.
client(Server_Address) ->
Server_Address ! {request, self()},
receive
{hit_count,Number} ->
io:format("CLIENT ~w: Hit count was ~w~n", [self(),Number])
end.
owner(Server_PID) ->
timer:sleep(random:uniform(100)),
Server_PID ! {server_owner,self()},
receive
{hit_count,Number} when Number > 5 ->
io:format("OWNER: Hit count is ~w , reseting counter. ~n", [Number]),
Server_PID ! reset,
owner(Server_PID);
{hit_count,Number} when Number < 5 ->
io:format("OWNER ~w: Hit count was ~w~n", [self(), Number]),
owner(Server_PID)
end.
spawn_n(N, Server_PID) ->
if
N>0 ->
spawn(simple,client,[Server_PID]),
timer:sleep(random:uniform(100)),
spawn_n(N-1,Server_PID);
N==0 ->
io:format("Last client spawned. ~n")
end.
start(N) ->
Server_PID = spawn(simple,server,[0]),
spawn(simple,owner,[Server_PID]),
spawn(simple,spawn_n,[N,Server_PID]).
main([Arg]) ->
N = list_to_integer(atom_to_list(Arg)),
start(N),
init:stop().
Here's an example I get when running it:
erl -noshell -s simple main 20
SERVER <0.28.0>: Client request recieved from <0.31.0>
CLIENT <0.31.0>: Hit count was 1
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.32.0>
OWNER <0.29.0>: Hit count was 1
CLIENT <0.32.0>: Hit count was 2
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.33.0>
OWNER <0.29.0>: Hit count was 2
CLIENT <0.33.0>: Hit count was 3
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.34.0>
OWNER <0.29.0>: Hit count was 3
CLIENT <0.34.0>: Hit count was 4
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.35.0>
OWNER <0.29.0>: Hit count was 4
CLIENT <0.35.0>: Hit count was 5
SERVER <0.28.0>: Owner request recieved from <0.29.0>
SERVER <0.28.0>: Client request recieved from <0.36.0>
CLIENT <0.36.0>: Hit count was 6
SERVER <0.28.0>: Client request recieved from <0.37.0>
CLIENT <0.37.0>: Hit count was 7
SERVER <0.28.0>: Client request recieved from <0.38.0>
CLIENT <0.38.0>: Hit count was 8
SERVER <0.28.0>: Client request recieved from <0.39.0>
CLIENT <0.39.0>: Hit count was 9
SERVER <0.28.0>: Client request recieved from <0.40.0>
CLIENT <0.40.0>: Hit count was 10
SERVER <0.28.0>: Client request recieved from <0.41.0>
CLIENT <0.41.0>: Hit count was 11
SERVER <0.28.0>: Client request recieved from <0.42.0>
CLIENT <0.42.0>: Hit count was 12
SERVER <0.28.0>: Client request recieved from <0.43.0>
CLIENT <0.43.0>: Hit count was 13
SERVER <0.28.0>: Client request recieved from <0.44.0>
CLIENT <0.44.0>: Hit count was 14
SERVER <0.28.0>: Client request recieved from <0.45.0>
CLIENT <0.45.0>: Hit count was 15
SERVER <0.28.0>: Client request recieved from <0.46.0>
CLIENT <0.46.0>: Hit count was 16
SERVER <0.28.0>: Client request recieved from <0.47.0>
CLIENT <0.47.0>: Hit count was 17
SERVER <0.28.0>: Client request recieved from <0.48.0>
CLIENT <0.48.0>: Hit count was 18
{error_logger,{{2011,6,27},{12,57,8}},"~s~n",["Error in process <0.28.0> with ex
it value: {terminated,[{io,format,[<0.22.0>,\"SERVER ~w: Client request recieved
from ~w~n\",[<0.28.0>,<0.49.0>]]},{simple,server,1}]}\n"]}
I don't get it. The processes just die or something? It shouldnt terminate!
I am running on windows 7 if it might be something windows-related.
Thanks
EDIT: heres what happens by doing application:start(sasl). before:
C:\Program Files\erl5.8.4\bin>erl
Eshell V5.8.4 (abort with ^G)
1> application:start(sasl).
ok
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.37.0>},
{name,alarm_handler},
{mfargs,{alarm_handler,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.38.0>},
{name,overload},
{mfargs,{overload,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_sup}
started: [{pid,<0.36.0>},
{name,sasl_safe_sup},
{mfargs,
{supervisor,start_link,
[{local,sasl_safe_sup},sasl,safe
{restart_type,permanent},
{shutdown,infinity},
{child_type,supervisor}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
supervisor: {local,sasl_sup}
started: [{pid,<0.39.0>},
{name,release_handler},
{mfargs,{release_handler,start_link,[]}}
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
2>
=PROGRESS REPORT==== 27-Jun-2011::16:03:55 ===
application: sasl
started_at: nonode@nohost
2> simple:main(['20']).
ok
SERVER <0.42.0>: Client request recieved from <0.45.0>
3> CLIENT <0.45.0>: Hit count was 1
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.47.0>
3> OWNER <0.43.0>: Hit count was 1
3> CLIENT <0.47.0>: Hit count was 2
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.48.0>
3> OWNER <0.43.0>: Hit count was 2
3> CLIENT <0.48.0>: Hit count was 3
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.49.0>
3> OWNER <0.43.0>: Hit count was 3
3> CLIENT <0.49.0>: Hit count was 4
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.50.0>
3> OWNER <0.43.0>: Hit count was 4
3> CLIENT <0.50.0>: Hit count was 5
3> SERVER <0.42.0>: Owner request recieved from <0.43.0>
3> SERVER <0.42.0>: Client request recieved from <0.51.0>
3> CLIENT <0.51.0>: Hit count was 6
3> SERVER <0.42.0>: Client request recieved from <0.52.0>
3> CLIENT <0.52.0>: Hit count was 7
3> SERVER <0.42.0>: Client request recieved from <0.53.0>
3> CLIENT <0.53.0>: Hit count was 8
3> SERVER <0.42.0>: Client request recieved from <0.54.0>
3> CLIENT <0.54.0>: Hit count was 9
3> SERVER <0.42.0>: Client request recieved from <0.55.0>
3> CLIENT <0.55.0>: Hit count was 10
3> SERVER <0.42.0>: Client request recieved from <0.56.0>
3> CLIENT <0.56.0>: Hit count was 11
3> SERVER <0.42.0>: Client request recieved from <0.57.0>
3> CLIENT <0.57.0>: Hit count was 12
3> SERVER <0.42.0>: Client request recieved from <0.58.0>
3> CLIENT <0.58.0>: Hit count was 13
3> SERVER <0.42.0>: Client request recieved from <0.59.0>
3> CLIENT <0.59.0>: Hit count was 14
3> SERVER <0.42.0>: Client request recieved from <0.60.0>
3> CLIENT <0.60.0>: Hit count was 15
3> SERVER <0.42.0>: Client request recieved from <0.61.0>
3> CLIENT <0.61.0>: Hit count was 16
3> SERVER <0.42.0>: Client request recieved from <0.62.0>
3> CLIENT <0.62.0>: Hit count was 17
3> SERVER <0.42.0>: Client request recieved from <0.63.0>
3> CLIENT <0.63.0>: Hit count was 18
3> {error_logger,{{2011,6,27},{16,3,58}},"~s~n",["Error in proc
exit value: {terminated,[{io,format,[<0.23.0>,\"SERVER ~w: Cli
ved from ~w~n\",[<0.42.0>,<0.64.0>]]},{simple,server,1}]}\n"]}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
另一个答案是正确的,但没有解释原因。
这是一个棘手的问题,答案(在某种程度上)在您的日志输出中:
第一个线索是 io:format/3 以“终止”和一些数据退出。
查看文档并搜索终止并没有给出任何结果。不过,查看 io.erl 内部给了我们答案。
当 io 设备关闭时,io.erl 的第 456 和 462 行返回 {error, Termination}。现在我们知道 io:format 可能会以终止状态退出。进一步看,我们可以看到这个返回值变成了上面第 74 行的错误消息(带有上下文):
如果你按照 request/2 的调用路径,你会发现一个可能的分支位于前面提到的 {error, returned} 。
所以,长话短说,标准输出下降了。
很可能是因为您使用
init:stop()
终止了系统。The other answer is correct, but it doesn't explain why.
It's a tricky question, and the answer is (sort of) in your log output:
The first clue is that io:format/3 exits with 'terminated' and some data.
Looking at the documentation and searching for terminated gives ... nothing. Looking inside io.erl gives us the answer though.
Line 456 and 462 of io.erl returns {error, terminated} when the io device is down. So now we know that io:format can potentially exit with status terminated. Looking further we can see that this return value turns into the above error message on line 74 (with context):
If you follow the call path for request/2 you will find that one possible branch is at the {error, terminated} mentioned earlier.
So, long story short, standard out is down.
Most likely since you killed your system with
init:stop()
.您在生成后立即调用
init:stop()
。您将如何确保所有流程都正确完成?您可能需要在main
中阻止接收,并在其他进程完成时通知主进程。You are calling
init:stop()
immediately after your spawns. How are you going to make sure all your processes are properly finished? You probably need to block on receive inmain
and notify main process when others are done.