[erlang-questions] Who called my gen_server?

Valentin Micic v@REDACTED
Thu Apr 27 11:30:51 CEST 2017


> Or, can I log all rpc_call(s) calling my gen_server?
> 
> /Frank
> 
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions



General comments about appropriateness of rpc notwithstanding….

Consider following statements (you may run them from the shell):

(tcap2@REDACTED)225> f(REX), REX=whereis(rex).  
<0.12.0>
(tcap2@REDACTED)226> unregister( rex ).         
true
(tcap2@REDACTED)227> catch register( rex, self() ).      
true

Then, you could go to the remote node's shell and run, say:

(tcap3@REDACTED)3> rpc:call( tcap2@REDACTED, erlang, now, [], 1000 ).

(NOTE 1: the caller wil timeout after one second)

At this point, your first node will receive a message, such that:

(tcap2@REDACTED)228> flush().
Shell got {'$gen_call',{<7155.38.0>,#Ref<7155.0.0.59>},
                       {call,erlang,now,[],<7155.31.0>}}
ok

(NOTE 2:  <<7155.38.0>> is pid() of the process that issued the call)
(NOTE 3:  <<7155.31.0>> is pid() of the group leader)

Thus, you could exploit this in order to write your own logger, which would front rex:

Consider below for incorporation in your code:


...
-export( [init/1, logger/0] ).
...
-record( state, {rex, logger} ).
...
init( _ )
->
...
  % ---------------
  % Redirecting REX
  % ---------------
  OldREX = whereis( REX ),
  unregister( rex ),
  register( rex, self() ),
  main_loop( #state{rex=OldREX, logger=spawn(?MODULE, logger, []} )
.

main_loop( S=#state{} )
->
    NewS = receive
        Request -> fwd_request(Request, S)
    end,
    main_loop( NewS )	
;
main_loop( {shutdown, #state{rex=OldREX, logger=LPID}} )
->
   % ---------------
   % Exit gracefully
   % ---------------
   unregister( rex ),
   register( rex, OldRex ),
   LPID ! shutdown,
   exit( normal )
.

fwd_request( Request={'$gen_call',{CallerPID,CallerRef}, {call,Mod,Func,Args,_CallerGroupLeader}}, S=#state{rex=OldRex, logger=LPID} )
->
   OldRex ! Request, 
   LPID   ! {log, CallerPid, CallerRef, Mod, Func, Args},
   S
;
fwd_request( shutdown, S ) -> {shutdown, S};
fwd_request( _, S )        -> S.

% ------
% LOGGER
% ------
logger()
->
   receive
      {log, CallerPid, CallerRef, Mod, Func, Args}
      ->
          ... Do some logging stuff ...
      ;
      shutdown -> exit( normal );
      _	       -> void 
   end,
   logger()
.

Kind regards

V/

PS
Just want to state the obvious: I did not compile this code. It could contain bugs, but it illustrates the point.



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170427/b22b0234/attachment.htm>


More information about the erlang-questions mailing list