Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  Can messages be sent to processes interactively?

jhague at dadgum.com
Posted: Thu May 20, 1999 5:35 pm Reply with quote
Guest
I've been doing a lot of sequential programming in Erlang, but have just
started getting into concurrency. It seems very obvious and
straightforward.

I wrote a quickie test process so I can start it up and send messages to
it interactively, just so I know that all is well:

-module(sample).
-export([start/0]).

start() -> spawn(sample, server, []).

server() ->
receive
stop -> ok;
Msg ->
io:fwrite("message received: ~w
", [Msg]),
server(N)
end.

This compiles just fine, and I can start the process from the Erlang
prompt with P = sample:start(), which results in a valid pid. "P ! 1."
from the command line, though, doesn't result in any fwrite output,
though. process_info(P) returns an atom of 'undefined'.

Is it not possible to do this sort of thing interactively? I've only
tried this using JAM under Windows. I haven't tried it with BEAM on my
Linux box yet.

James




Post generated using Mail2Forum (http://m2f.sourceforge.net)
jhague at dadgum.com
Posted: Thu May 20, 1999 6:08 pm Reply with quote
Guest
> server(N)
^
Dumb typo when I simplified the code for posting. That doesn't have any
effect on my question.

James



Post generated using Mail2Forum (http://m2f.sourceforge.net)
crd at inversenet.com
Posted: Thu May 20, 1999 6:13 pm Reply with quote
Guest
James Hague wrote:

> I wrote a quickie test process so I can start it up and send messages to
> it interactively, just so I know that all is well:
>
> -module(sample).
> -export([start/0]).
>
> start() -> spawn(sample, server, []).
>
> server() ->
> receive
> stop -> ok;
> Msg ->
> io:fwrite("message received: ~w
", [Msg]),
> server(N)
> end.
>
> This compiles just fine

No, it doesn't. Variable N is unbound, and no function server/1 is defined.
Furthermore, since you didn't export server/0, you can't spawn it.

If you really want to be sure (interactively) that your process has started,
have it output something when it starts up.

This ought to compile and work as you expect:

--- cut here ---
-module(sample).

-export([start/0, server/0]).

start() -> spawn(?MODULE, server, []).

server() ->
io:fwrite("server started
"),
receive
stop -> io:fwrite("server stopping
"), ok;
Msg -> io:fwrite("message received: ~w
", [Msg])
end.
--- cut here ---

You should find that you can send messages to this server from the Erlang
shell.

Craig




Post generated using Mail2Forum (http://m2f.sourceforge.net)
crd at inversenet.com
Posted: Thu May 20, 1999 6:27 pm Reply with quote
Guest
James Hague wrote:

> > server(N)
> ^
> Dumb typo when I simplified the code for posting. That doesn't have any
> effect on my question.

Well, it does, in a way, since it means the code won't even compile, much
less work. Most readers will probably stop at that point, and fail to notice
the more subtle problem that you didn't export server/0, which I think is
what caused your original code (pre-simplification) to not work. (Unless
that's another thing that got messed up in your "simplification", in which
case you probably left out the real problem altogether, since the simplified
code behaves as expected once the export and the server(N) are corrected.)

Moral: always test your simplified example before mailing it out!

Craig




Post generated using Mail2Forum (http://m2f.sourceforge.net)
jhague at dadgum.com
Posted: Thu May 20, 1999 8:03 pm Reply with quote
Guest
Craig Dickson wrote:
>
>Well, it does, in a way, since it means the code won't even compile, much
>less work. Most readers will probably stop at that point, and fail to
notice
>the more subtle problem that you didn't export server/0, which I think is
>what caused your original code (pre-simplification) to not work. (Unless
>that's another thing that got messed up in your "simplification", in
which
>case you probably left out the real problem altogether,

I agree, I should have made sure my code still compiled after deleting
that one parameter. And I knew, as soon as I sent the mail, that I'd get
a response like this. Ten years of Usenet makes one good at predicting
human nature :)

Yes, I did not realize that server functions always need to be exported. I
see now that spawm() always returns a pid even when the arguments are
nonsensical: spawn(mud, mud, []). But everything works fine now and I'm
happily writing concurrent code.

All the best,
James



Post generated using Mail2Forum (http://m2f.sourceforge.net)
crd at inversenet.com
Posted: Thu May 20, 1999 8:37 pm Reply with quote
Guest
James Hague wrote:

> And I knew, as soon as I sent the mail, that I'd get
> a response like this. Ten years of Usenet makes one good at predicting
> human nature :)

I'm not quite sure what you mean. From my own ten years or so of Usenet, I
expect almost any public online discussion to be periodically interrupted by
mad flamers, so your statement leads me to wonder if you interpreted
something in my reply as being of that nature. If so, then I apologize; it
wasn't meant harshly.

Craig




Post generated using Mail2Forum (http://m2f.sourceforge.net)
jhague at dadgum.com
Posted: Thu May 20, 1999 9:41 pm Reply with quote
Guest
Craig Dickson wrote:
>
> I'm not quite sure what you mean. From my own ten years or so of Usenet, I
> expect almost any public online discussion to be periodically interrupted by
> mad flamers, so your statement leads me to wonder if you interpreted
> something in my reply as being of that nature. If so, then I apologize; it
> wasn't meant harshly.

No, no, no, I didn't interpret it as harsh. I'm just sensitive to what I
see as "predictable" reactions. If someone posted "I'm writing a
spreadsheet in Pascal for xwindows and I'm looking GUI library
recommendations," you just *know* somebody is going to respond with "You
should use C, not Pascal!" And so on.

I was very hesitant to post any code, because I expected to get flak for
indentation style or lack of comments or variable naming conventions, or a
dumb typo. I made the latter, unfortunately! Being able to see through
such "mistakes" is a good thing. But, as I'll freely admit, my typo did
muddle the question somewhat.

Thanks for the help. Erlang is the most (programming-related) fun I've
had in a long while. And if the "Concurrent Programming in Erlang"
authors are reading this--great job! It's a great read (and thankfully,
not as oversized as most language introductions).

James




Post generated using Mail2Forum (http://m2f.sourceforge.net)
tobbe at serc.rmit.edu.au
Posted: Fri May 21, 1999 12:06 am Reply with quote
Guest
> Yes, I did not realize that server functions always need to be exported. I
> see now that spawm() always returns a pid even when the arguments are
> nonsensical: spawn(mud, mud, []). But everything works fine now and I'm
> happily writing concurrent code.

A little helpful comment here:

Think of spawn/3 as:

1. Create a new (empty) erlang process.
2. Perform an apply/3 in the new process.

To be able to do the apply/3 you have to export the M:F/A.

Another little comment: It is very instructive to make
use of the debugger, especially when you write concurrent code.
To use it do the following from your erlang shell prompt;

1> ii(YOUR-MUDULE-NAME).

2> iaa(init).

3> YOUR-MODULE-NAME:foo(....).

A window will now pop-up the first time you execute
the debugged (interpreted) code. From here: singe-step,
inspect variables, etc...

Another useful command is: im().
It will bring up a monitor window displaying all
processes currently being debugged. Attach yourself
to a process by double-click on one of the lines (in the
displayed matrix) representing the process.

Finally: ib(YOUR-MODULE-NAME, LINE-NO).
Sets a break point in a module. By using: iaa(break)
the window will now pop-up when you hit the break point.

All of this can of course be done from the menues of
the monitor window, but the command interface I have
showed here is much faster and easier to use (IMHO... Wink.

/Tobbe


Post generated using Mail2Forum (http://m2f.sourceforge.net)
joe at bluetail.com
Posted: Fri May 21, 1999 8:15 am Reply with quote
Guest
Craig Dickson wrote:

> James Hague wrote:
>
> > I wrote a quickie test process so I can start it up and send messages to
> > it interactively, just so I know that all is well:
> >
> > -module(sample).
> > -export([start/0]).
> >
> > start() -> spawn(sample, server, []).
> >
> > server() ->
> > receive
> > stop -> ok;
> > Msg ->
> > io:fwrite("message received: ~w
", [Msg]),
> > server(N)
> > end.
> >
> > This compiles just fine
>
> No, it doesn't. Variable N is unbound, and no function server/1 is defined.
> Furthermore, since you didn't export server/0, you can't spawn it.
>
> If you really want to be sure (interactively) that your process has started,
> have it output something when it starts up.
>
> This ought to compile and work as you expect:
>
> --- cut here ---
> -module(sample).
>
> -export([start/0, server/0]).
>
> start() -> spawn(?MODULE, server, []).
>
> server() ->
> io:fwrite("server started
"),
> receive
> stop -> io:fwrite("server stopping
"), ok;
> Msg -> io:fwrite("message received: ~w
", [Msg])
> end.
> --- cut here ---
>
> You should find that you can send messages to this server from the Erlang
> shell.
>
> Craig

Right - but I think I should not point out the difference between spawn and
spawn_link

Suppose I write the following:


-module(sample).
-export([start/0, server/0]).

start() -> spawn_link(sample, server, []).

server() ->
receive
stop -> ok;
Msg ->
1 = 2,
server()
end.

This contains a deliberate error but it won't be reported
1> P=sample:start().
<0.30.0>
2> P!a
2> .
a
3> P!2.
2

The process died but we saw nothing. P is still a process reference but it
point to crap. P!2 etc. succeeds.

(X!Y has send and pray semantics :-)

Now change spawn to spawn_link. "spawn_link" says spawn the process and link
to it for
error handling purposes. Deliver an exit message if something goes wrong. so
...

1> P=sample:start().
<0.30.0>
2> P!1.
1

=ERROR REPORT==== 21-May-1999::10:09:00 ===
<0.30.0> error: {badmatch,2} in sample:server/0
** exited: {{badmatch,2},{sample,server,0}} **
3> P!2.
2
4> process_info(P).
undefined
5>

Line 1> caused the spawned process to be linked to the shell process.

Line 2> Sends a message to P. The process crashes with a badmatch error (i.e. 1
cannot be 2)
Because it is linked to the shell an exit message is sent to the shell. The
shell has a handler
which prints the value of the exit signal.

Line 3> succeeds. P is still a reference to a proceess but the process is not
dead so P ! 2 succeeds

Line 4> you can inspect the "state" of P - it is of course, dead.

It's often a good idea to use spawn_link and lot and spawn sparingly if you're
a beginner
That way you get the default error handling mechanisms - gurus would probably
use
spawn a lot and spawn_link sparingly and make their own error handling
mechanisms.

/Joe








Post generated using Mail2Forum (http://m2f.sourceforge.net)
crd at inversenet.com
Posted: Fri May 21, 1999 1:36 pm Reply with quote
Guest
Joe Armstrong <joe_at_bluetail.com> wrote:

> It's often a good idea to use spawn_link and lot and spawn sparingly if
> you're a beginner
> That way you get the default error handling mechanisms - gurus would
> probably use spawn a lot and spawn_link sparingly and make their own error
> handling mechanisms.

I thought spawn_link together with exit trapping was pretty much the best
way to deal with failures in worker processes. Would a real Erlang guru do
something different? If so, what?

Craig




Post generated using Mail2Forum (http://m2f.sourceforge.net)
mbjk at eecs.umich.edu
Posted: Fri May 21, 1999 7:11 pm Reply with quote
Guest
"Craig Dickson" <crd_at_inversenet.com> wrote:
>
> I thought spawn_link together with exit trapping was pretty much the best
> way to deal with failures in worker processes. Would a real Erlang guru do
> something different? If so, what?

Take a look at the functions in the module proc_lib. The functions
proc_lib:spawn and spawn_link are as the BIFs, but creates a crash
report, should the new process crash. There are also two functions
start & start_link, which are synchronous - they return when the new
process has been started and initialized. All system processes use
these functions (most of them use proc_lib:start_link indirectly via
gen_server:start_link).

To see the crash reports, statr erlang as:

erl -boot start_sasl -sasl errlog_type error

(see sasl(6) for details about errlog_type)


/martin


Post generated using Mail2Forum (http://m2f.sourceforge.net)
klacke at bluetail.com
Posted: Fri May 21, 1999 8:38 pm Reply with quote
Guest
> start() -> spawn(sample, server, []).
>
> server() ->
> receive
> stop -> ok;
> Msg ->
> io:fwrite("message received: ~w
", [Msg]),
> server(N)
> end.
>
> This compiles just fine, and I can start the process from the Erlang
> prompt with P = sample:start(), which results in a valid pid. "P ! 1."
> from the command line, though, doesn't result in any fwrite output,
> though. process_info(P) returns an atom of 'undefined'.
>


One little error there, the call

> server(N)

calls a function (called "server") with 1 (one) argument in
the local module.
Nu such function exists, thus the process will exit.

Since the process has no links to any other processes
it will silently exit, thus the

> process_info(P) returns an atom of 'undefined'.

So, change

> server(N)

to

server()

and you'll be on your way

Cheers

/klacke




Post generated using Mail2Forum (http://m2f.sourceforge.net)
klacke at bluetail.com
Posted: Fri May 21, 1999 8:59 pm Reply with quote
Guest
>
> I've been doing a lot of sequential programming in Erlang, but have just
> started getting into concurrency. It seems very obvious and
> straightforward.
>
> I wrote a quickie test process so I can start it up and send messages to
> it interactively, just so I know that all is well:
>
> -module(sample).
> -export([start/0]).
>
> start() -> spawn(sample, server, []).
>
> server() ->
> receive
> stop -> ok;
> Msg ->
> io:fwrite("message received: ~w
", [Msg]),
> server(N)
> end.
>


And yet another little error, there is no function
called sample:server/0 nor sample:server/1 *exported*
from the module.

It might seem pretty idiotic that any function that is spawned
need to be exported but that is the way it is.

(applies to apply/3 too !!!)

So, change

> -export([start/0]).

to

-export([start/0, server/0]).

Personally I like the

-compile(export_all)

switch while I'm developing, this way I need not bother
about that at that stage.


Cheers

/klacke

PS. There's a bit of one of my favourite topics in here -- namely
software archeology. Why is it like this. The obvious thing would
be to spawn a fun instead of a tripple M:F/A

start() ->
spawn(fun() -> server() end).

????










Post generated using Mail2Forum (http://m2f.sourceforge.net)

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum