3
votes

I am building a network router application using Erlang OTP framework.

In its process of running a Supervisor creates two genservers and each estagen_server:call(CurrentProcName,{BinEvent,UniqueTrxId,MdPid},infinity),blishes a tcp connection to two individual servers.

Now while running the application , It happens that one genserver receives a duplicate event , on such a case I want that event to be processed by the second gen_server .

For this , i am calling gen_server:call(NextProcName,{BinEvent,UniqueTrxId,MdPid},infinity),

This function I am calling inside the gen_server module when the condition for duplicate event satisfies.

NextProcName :: It is the registered name for the second gen_server

NOTE :: the code remains the same for both gen_server's

The problem is I am able to duplicate events but the event is somehow not getting passed to the second gen_server :(

Please suggest If I am doing it in the wrong way or not.

1

1 Answers

3
votes

If you can share the source, it would be appreciated.

Are you sure the message is really received or do you just not receive an answer?

The most plausible problem I see here is that you're forwarding a message in a synchronous manner. If it's not the case, then you can disregard my post entirely. For now, let's see how synchronous forwarding plays out:

 client          server1             server2
   |                |                   |
   >--- Msg1 ----> (ok)                 |
(waits S1)          |                   | 
  (ok) <-- Reply ---<                   |
   >--- Msg2 ----> (ok)                 |
(waits S1)          >----- Msg2 -----> (ok)
(waits S1)      (waits S2) <--- Reply --<      
(waits S1)      (Waits S2)              |

          *Stuff crashes*

This is not exactly clear, but it shows what's going on. Here Server1 is basically still counting as processing the message Msg2 to the gen_server behaviour, and will thus never read the reply from Server2 that it is waiting for. This will usually end up in a timeout and crash.

The correct way to do this is to instead send an asynchronous call (a cast) from Server1 to Server2, including the From variable so thatServer2 can reply with gen_server:reply/2 to substitute itself to Server1. Server1 should then return with a noreply tuple. This will free Server1's process and it'll be able to keep on processing other stuff.