[newbie] accept()-ing process under supervision (was:Erlangish way of Iterator pattern)
Joe Armstrong (AL/EAB)
joe.armstrong@REDACTED
Wed Jan 26 16:07:29 CET 2005
Tricky - there is a spectrum of answers here:
"make sure that it is always listening" could mean lot's of different things:
1) Is the listening process (ie the process which evaluates tcp_accept)
still alive?
2) Is the listening process responsive?
ie is it accepting connections and doing what it is supposed to do?
In my example tcp_server might happily accept connections and spawn a new handler
per connection - but these handlers might deadlock, or go into infinite loops or something and not respond as
expected (Now I don't mean here that the handlers *crash* - because crashes will be detected and the
socket will be closed) - it's just that they don't work properly.
Detecting 1) is trivial (just link to the process). 2) requires some kind of end-to-end confirmation
ie a program *outside* Erlang which periodically asks the server to prove that it running.
Say ask it what factorial 42 is once every minute.
<<to be really safe - the probing program should be on a *different* processor -
because of "Joe's law"
+------------+
| Joe's law |
+-----------------------------------------+
| To do fault-tolerant computations |
| you need at least 2 computers |
+-----------------------------------------+
Obviously :-)
>>
An easy solution (somewhere between 1 and 2 here) can be to use "on-exit" defined thus:
on_exit(Pid, Fun) ->
spawn_fun(fun() ->
process_flag(trap_exit, true),
link(Pid),
receive
{'EXIT', Pid, Why} ->
Fun(Why)
end
end).
You can use on_exit to restart a function if it fails.
[almost] like this:
keep_alive(Fun) ->
Pid = spawn(fun() -> Fun() end),
on_exit(Pid,
fun({'Exit', normal} ->
true;
{'EXIT', Other} ->
%% restart it
keep_alive(Fun)
end).
Cheers
/Joe
[almost] - the code above is incorrect - and is merely to illustrate the idea -
why is it incorrect? (ten brownie points for the first correct explanation of the error :-)
> -----Original Message-----
> From: owner-erlang-questions@REDACTED
> [mailto:owner-erlang-questions@REDACTED]On Behalf Of Gaspar
> Chilingarov
> Sent: den 26 januari 2005 12:07
> To: erlang-questions@REDACTED
> Subject: Re: [newbie] accept()-ing process under supervision
> (was:Erlangish way of Iterator pattern)
>
>
> Yeah, i know, you have some tasty things on your pages :)
>
> but i wish to run process which does gen_tcp:accept under
> supervision --
> just to be sure that it always listening. processes which serve each
> connections are out of my interest (for now) -- they can
> crash when they
> want :)
>
>
> Joe Armstrong (AL/EAB) wrote:
> > To solve problems like this I almost always use a module
> called tcp_server which is
> > available at
> >
> > http://www.sics.se/~joe/tutorials/web_server/tcp_server.erl
> >
> > To use it call:
> >
> > tcp_server:start(Port, Fun, Max)
> >
> > This starts a server which listens to Port up to Max
> simultaneous connections on Port are allowed.
> >
> > The *first* time a connection is made to Port Then
> Fun(Socket) is called.
> > Thereafter messages to the socket result in messages to the handler.
> >
> > A typical server is usually written like this:
> >
> > start_server(Port) ->
> > S = self(),
> > process_flag(trap_exit, true),
> > tcp_server:start_raw_server(Port,
> > fun(Socket) ->
> input_handler(Socket, S) end,
> > 15,
> > 0)
> > loop().
> >
> > The loop() process is a central controller that all
> processes can use to synchronize amongst themselves if
> necessary It ends up as the variable "Controller" in the input_handler
> >
> > A typical server is written like this:
> >
> > input_handler(Socket, Controller) ->
> > receive
> > {tcp, Socket, Bin} ->
> > ...
> > gen_tcp:send(Socket, ...)
> > {tcp_closed, Socket} ->
> >
> > Any ->
> > ...
> > end.
> >
> > tcp_server can be used to build many different things. For
> example a web server or wiki system.
> >
> > If you want to see how to make a web server using
> tcp_server read my second "spitting in the dust tutorial" on how to
> > make a web server.
> >
> > This is at
> >
> > http://www.sics.se/~joe/tutorials/web_server/web_server.html
> >
> > This has all the code for a simple web server - the web
> server itself is split into a http parser (222 lines of code)
> > a server (104 lines) and the tcp_server (175) lines.
> >
> > I'll show you the code for the web server - it's like this:
> >
> > server(Client, Master) ->
> > receive
> > {Client, closed} ->
> > true;
> > {Client, Request} ->
> > Response = generate_response(Request),
> > Client ! {self(), Response},
> > server(Client, Master)
> > after 5000 ->
> > true
> > end.
> >
> > That's all :-)
> >
> > The structure used in the web server provides a useful
> model of how to build these type of things. It has
> >
> > - a connection handler (tcp_server) which manages tcp sessions
> > - a device driver that parses HTTP messages and turns
> them into Erlang messages
> > - a pure Erlang server
> >
> > The general philosophy is "pretend that all things in the
> outside world are Erlang processes" - thus to program a web
> > server we model the browser as an Erlang process - it sends
> a {get, File} message to the server. The job of the
> > connection handler and device driver is to take the HTTP
> protocol message and turn them into Erlang terms.
> > Having done so, writing the server is a doodle.
> >
> > Cheers
> >
> > /Joe
> >
> >
> >
> >
> >>-----Original Message-----
> >>From: owner-erlang-questions@REDACTED
> >>[mailto:owner-erlang-questions@REDACTED]On Behalf Of Gaspar
> >>Chilingarov
> >>Sent: den 25 januari 2005 15:20
> >>To: erlang-questions@REDACTED
> >>Subject: [newbie] Erlangish way of Iterator pattern
> >>
> >>
> >>Hello!
> >>
> >>I'm beginning to program in erlang and hit the following problem.
> >>in mainstream language i will do the following -- create
> >>Iterator class
> >>to read data from socket or file
> >>i.e. class with Open/GetNext functions. Open should just do
> >>all work for
> >>preparing data source and GetNext will return lines of data or
> >>EOF(freeing resources when reaching EOF).
> >>
> >>
> >>what i have in erlang -- i have erlang process, which can
> accept data
> >>messages and eof messages and do processing. another process hangs
> >>around, waiting for TCP connection and feeding first process
> >>with data
> >>read from TCP. in the same time i have shell script which
> runs once a
> >>minute and feeds data from some file(or piped command line)
> >>to TCP port.
> >>
> >>now i want to get rid of shell script, but i wish to have separate
> >>module which will do this -- i.e. 1. running periodically external
> >>command, 2. feeding to another process.
> >>
> >>are there any idioms in Erlang for this or it should be
> >>implemented in
> >>straight way -- i.e. just another process sitting there and
> >>doing it's
> >>job -- file reading/parsing/feeding to another process ?
> >>
> >>
> >>
> >>--
> >>Gaspar Chilingarov
> >>System Administrator
> >>
> >>t +3749 419763
> >>w www.web.am
> >>e nm@REDACTED
> >>
> >
> >
>
>
> --
> Gaspar Chilingarov
> System Administrator
>
> t +3749 419763
> w www.web.am
> e nm@REDACTED
>
More information about the erlang-questions
mailing list