[erlang-questions] Problem with io monitor - a bug?
Patrik Nyblom
pan@REDACTED
Tue Dec 4 11:48:06 CET 2012
Hi,
No, it's not a bug. It's a race in the calling code. The spawned process
sends the first io-request and the shell sends the second. The first
"read" will be overridden while the shell's request is served. They are
so to say stacked. Having two processes (the shell and your newly
spawned process) reading from the same io-device is generally not a good
idea, they are competing for a single resource that is kind of hard to
share... You have to keep other processes from tampering with your
terminal while you're reading it, in this case by letting the shell wait
for your process.
In fact, you actually get your prompt from the spawned process written,
but the shell will override/overwrite it. Try sleeping the shell for a
second and your prompt will temporarily be shown, but then the shell
comes back and your prompt disappears again. If you sleep for a while in
the child process before reading, the child will instead override the
shell. There's no telling which one will be stacked upon the other. It's
kind of impossible to determine which order is preferred by the
caller... So, your program has to decide on the order by synchronizing
it's activities.
Example:
1> Prompt = "Please enter data: ".
2> F = fun() -> try Result = io:read(Prompt), io:format("Res:
~p~n",[Result]) catch A:B -> io:format("Read error: ~p:~p~n",[A,B]) end end.
3> {Pid,Ref} = spawn_monitor(F), receive after 1000 -> ok end.
%% "Please Enter data: " will be shown for a second, then disappears and
the shell prompt comes back.
4> receive after 1000 -> ok end.
%% Please enter data will appear again, but disappears after a second again.
5> receive {'DOWN',Ref,process,Pid,_} -> ok end.
Please enter data: hi.
Res: {ok,hi}
%% Now try waiting a second to make the shell send the io-request before
your spawned process
6> G = fun() -> try receive after 1000 -> ok end, Result =
io:read(Prompt), io:format("Res: ~p~n",[Result]) catch A:B ->
io:format("Read error: ~p:~p~n",[A,B]) end end.
7> spawn(G).
%% First you will see the shell prompt for ~ a second, then you will get:
Please enter data: hello.
Res: {ok,hello}
8>
In other words, do not have two processes competing tor one terminal, it
will only give confusing results :)
Cheers,
/Patrik, OTP
On 11/30/2012 01:57 PM, Álvaro wrote:
> Dear all,
>
> Every time I run this simple code, my program gets stuck:
>
> > Pid = spawn (moduleName,myread,["hello"]).
>
> where:
>
> myread(Prompt)->
> try
> Result = io:read(Prompt),
> io:format("Res: ~p~n",[Result]),
> catch
> A:B->
> io:format("Read error: ~p:~p~n",[A,B]),
> false
> end.
>
>
> if I check the status of the process:
>
> > erlang:process_info(Pid).
>
> [{current_function,{io,wait_io_mon_reply,2}},
> {initial_call,{default_environment,myread,1}},
> {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,7},
> {reductions,28},
> {garbage_collection,[{min_bin_vheap_size,46368},
> {min_heap_size,233},
> {fullsweep_after,65535},
> {minor_gcs,0}]},
> {suspending,[]}]
>
>
> It seems to be stuck in the function io:wait_io_mon_reply/2 (surfing
> through io.erl I found that this function waits for a response from
> the process managing the io ). This process is not answering, hence
> my code stops working.
> I've checked that the "group_leader()" once I spawn the reading
> process is the same used by my shell.
>
> Any ideas on how to deal with it?
>
> Regards,
> Álvaro
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121204/cbeb5e99/attachment.htm>
More information about the erlang-questions
mailing list