1
votes

I noticed that messages sent to the pid of a gen_fsm process are matched in the state callbacks as events. Is this just accidental or can I rely on this feature?

Normally I would expect general messages sent to a gen_fsm to show up in the handle_info/3 callback and thought I would have to re-send it using gen_fsm:send_event.

Does gen_fsm try to match the message first to the state callback and then allways with the handle_info/3 callback? Or only if it doesn't match a state callback clause?

However when I try it my message seems to be handled twice according to debug output.

So basically the question can also be stated like: how to correctly handle received messages as events in gen_fsm state functions?


Clarification: that some of the events are occurring by getting messages passed should be considered given for this question.

I'm aware that in many cases its cleaner to make the protocol visible by using function calls into the fsm only.

I'm not so sure if this would improve the current framework where the mentioned gen_fsm has to fit in: Diverse protocol stacks where each layer calls a connect() function to attach (and sometimes start) the lower layer. Packets are sent to lower layers ba calling a function (send) and received by receiveing a message. Much like gen_tcp.

By looking at the code for gen_fsm I already figured out that general messages are only passed to handle_info, so only the question remains wether to call the state function directly from the handle_info/3 callback or resent using gen_fsm:send_event.

1
Have I understood you correctly here, are you using gen_fsm for only some of the protocol stack and not all of it? If so, why? Why not have all the Erlang part of the stack implemented in the same way? This would allow you to be consistent in how messages are sent and received.rvirding
I'm consistently unsing a {ok, Pid} = connect(), send(Pid, Data) and receiving {resp, Data} messages. So I'm consistent in the API of different modules in the stack. Where I'm not consistent is the handling of receive and send currently.Peer Stritzinger
But there is quite a bunch of preexistent code using this paradigm so its an effort to change everything over. Reason for not using gen_fsm for all parts of the stack is that its actually very diverse protocols (automotive bus protocols) multiplexed over usb. So the parts of the stack vary between gen_server, simple ad/hoc server and stateless encode/decode filters and gen_fsm of course.Peer Stritzinger
I have picked up the suggestion for a better design of the whole protocol stack and started a new question to discuss how the best way would be to do this: "How to design a flexible Erlang protocol stack creation API" See "Linked" sectionPeer Stritzinger

1 Answers

1
votes

General messages are handled by handle_info callback, unless you have something like this in your code:

handle_info(Info, StateName, StateData) -> ?MODULE:StateName(Info, StateData).

Which avoids resending, but I do not recommend neither that, nor resending.

Delivering events exclusively by means of API calls encapsulating send_event/sync_send_event/send_all_state_event/sync_send_all_state_event makes protocol explicit. Which is a right thing, as it is easier to understand, maintain and document with edoc.