gen_server的enter_loop分析
http://my.oschina.net/astute/blog/119250?p=1
在看ranch user guide的过程中,发现实现protocol handler需要使用特殊的gen_server形式,也就是enter_loop函数调用,事例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-module(echo_protocol). -behaviour(ranch_protocol). - export ([start_link/4]). - export ([init/4]). start_link(ListenerPid, Socket, Transport, Opts) -> Pid = spawn_link(?MODULE, init, [ListenerPid, Socket, Transport, Opts]), {ok, Pid}. init(ListenerPid, Socket, Transport, _Opts = []) -> ok = ranch:accept_ack(ListenerPid), loop(Socket, Transport). loop(Socket, Transport) -> case Transport:recv(Socket, 0, 5000) of {ok, Data} -> Transport:send(Socket, Data), loop(Socket, Transport); _ -> ok = Transport:close(Socket) end. |
实现ranch的protocol handler只需要实现start_link函数即可,函数中需要启动一个新的进程,新的进程需要调用accept_ack函数来绑定socket的owner进程。
如果回调要实现gen_server行为模式的话,Listener进程调用模块的start_link方法,内部同步的启动gen_server进程,并且等待gen_server进程调用init函数返回,如果这个时候在init的方法中调用accept_ack方法,就会造成循环调用,造成死锁。
ranch提供的方法如下,使用gen_server的enter_loop方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-module(my_protocol). -behaviour(gen_server). -behaviour(ranch_protocol). - export ([start_link/4]). - export ([init/1]). %% Exports of other gen_server callbacks here. start_link(ListenerPid, Socket, Transport, Opts) -> proc_lib:start_link(?MODULE, [[ListenerPid, Socket, Transport, Opts]]). init(ListenerPid, Socket, Transport, _Opts = []) -> ok = proc_lib:init_ack({ok, self()}), %% Perform any required state initialization here. ok = ranch:accept_ack(ListenerPid), ok = Transport:setopts(Socket, [{active, once}]), gen_server:enter_loop(?MODULE, [], {state, Socket, Transport}). %% Other gen_server callbacks here. |
通常情况下启动gen_server,需要调用gen_server:start_link(),参数中设置回调模块,这样的话像上面的分析,是会有死锁的问题的。
规避这个问题就是使用enter_loop方法。这个方法可以让已经存在的独立进程成为gen_server进程,在进入普通的gen_server循环之前执行设定的逻辑。
Listener进程调用proc_lib:start_link方法,创建新进程A,A执行init方法,调用proc_lib:init_ack()方法,告诉listener进程A进程已经启动,此时Listener进程就可以返回了。然后A进程再执行accept_ack()方法,最后调用enter_loop方法,让自己进入gen_server的执行循环。
gen_server的enter_loop分析的更多相关文章
- Gen_server行为分析与实践
1.简介 Gen_server实现了通用服务器client_server原理,几个不同的客户端去分享服务端管理的资源(如图),gen_server提供标准的接口函数和包含追踪功能以及错误报告来实现通用 ...
- gen_server port 调用receive_match 问题
问题由来 前些天对系统做了一个优化,将原来从queue 轮询刷出数据后每条消息一个 spawn 进程单独处理,修改为批量刷出.一条一条刷轮询刷 queue 存在问题:刷queue 进程太多时,占用CP ...
- Erlang generic standard behaviours -- gen_server module
在分析完gen module (http://www.cnblogs.com/--00/p/4271386.html)之后,就可以开始进入gen_server 的主体module 了.gen_serv ...
- Supervisor行为分析和实践
1.简介 Erlang要编写高容错性.稳定性的系统,supervisor就是用来解决这一问题的核心思想.通过建立一颗监控树,来组织进程之间的关系,通过确定重启策略.子进程说明书等参数信息来确定 ...
- Erlang模块gen_server翻译
gen_server 概要: 通用服务器行为描述: 行为模块实现服务器的客户端-服务器关系.一个通用的服务器进程使用这个模块将实现一组标准的接口功能,包括跟踪和错误报告功能.它也符合OTP进程监控树. ...
- Erlang gen_server进程花样作死
本文主要记录各种情况下gen_server进程退出的表现. 研究动机起源于Elixir/Phoenix框架中遇到的一个进程异常退出问题.因为网络异常,客户端超过一段时间未发来消息,channel进程( ...
- gen_server terminate与trap_exit
不论是新手还是熟手,写gen_server时常会遇到terminate/2,有时执行,有时却不执行的困惑. 比如stackoverflow中的Handling the cleanup of the g ...
- Erlang的gen_server的terminate()/2未执行
官方资料参考: Module:terminate(Reason, State) Types: Reason = normal | shutdown | {shutdown,term()} | term ...
- [Erlang21]Erlang性能分析工具eprof fporf的应用
前段时间项目改代码突然cpu波动很大,排查了好久都没有找到原因,只能求助于性能测试工具 : <<Erlang程序设计>>----Joe Armstorng[哈哈,登月第一人 ...
随机推荐
- android 闹钟提醒并且在锁屏下弹出Dialog对话框并播放铃声和震动
android 闹钟提醒并且在锁屏下弹出Dialog对话框并播放铃声和震动 1.先简单设置一个闹钟提醒事件: //设置闹钟 mSetting.setOnClickListener ...
- 3.实战HTML+CSS布局(实例入门篇)
转自:https://www.cnblogs.com/hmyprograming/archive/2012/03/23/2414373.html 学习这篇入门教程我们假定你已经具有了一定的HTML基础 ...
- HTML基础第四讲---图像
转自:https://blog.csdn.net/likaier/article/details/326735 图像,也就是images,在html语法中用img来表示,其基本的语法是: < ...
- mysql测试spring事务是否生效
同时对三张表进行插入操作,事务保证完整性.下面进行简单测试: 1. 锁定表 锁定用户表 LOCK TABLES user WRITE; 查看表是否锁定: show ; 显示被锁定的表. 2. 验证在同 ...
- FAILOVER详细步骤
FAILOVER详细步骤 1.Flush主库任何未传输的redo到目标备库 如果primary可以mount,则可以flush任何主库的未传输redo到备库,如果操作成功返回,则可以保证failove ...
- COGS——C2274. [HEOI 2016] tree
http://www.cogs.pro/cogs/problem/problem.php?pid=2274 ★☆ 输入文件:heoi2016_tree.in 输出文件:heoi2016_tre ...
- Android RxJava基本流程和lift源码分析
基本结构 我们先来看一段最基本的代码,分析这段代码在RxJava中是如何实现的. Observable.OnSubscribe<String> onSubscriber1 = new Ob ...
- <一> 爬虫的原理
一.爬虫是什么? #1.什么是互联网? 互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样. #2.互联网建立的目的? 互联网的核心价值在于数据的共享/传递:数 ...
- uva 10710 - Chinese Shuffle(完美洗牌)
option=com_onlinejudge&Itemid=8&category=474&page=show_problem&problem=1651"> ...
- js面向对象的选项卡
前言: 选项卡在项目中经常用到,也经常写,今天在github突然看到一个面向对象的写法,值得收藏和学习. 本文内容摘自github上的 helloforrestworld/javascriptLab ...