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[哈哈,登月第一人 ...
随机推荐
- 1.3 Quick Start中 Step 2: Start the server官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Step 2: Start the server Step : 启动服务 Kafka ...
- robotframework Selenium2+RFS自动化测试
支持浏览器版本:Google Chrome (64位) 52.0.2743.82 正式版 52.0.2743.6_chrome_installer 64位 下载地址:http://www.online ...
- 原生js大总结八
071.如何组织事件冒泡 利用事件对象属性:stopPropagation 和 cancelBubble stopPropagetion是一个方法:e.stopPropagetion(); ...
- iOS 中使用 XIB 自定义cell的两种方法以及编译出现常见 的错误 (xcode6.0之后)
一. 注册cell 1.创建自定义cell并勾选 xib :(勾选xib就会自动生成与cell文件关联的xib) 2.在 tableViewController里注册自定义Cell (或者遵守tabl ...
- CentOS7安装docker 18.06
原文:CentOS7安装docker 18.06 一.CentOS Docker 安装 参考docker 官方网站:https://docs.docker.com/install/linux/dock ...
- BZOJ 3038 上帝造题的七分钟2 树状数组+并查集
题目大意:一个序列,有两种操作.1.将一段数中的每个数开根号.2.查询一段数的和. 思路:和3211是一个题,有兴趣的能够看看我的那篇博客. CODE: #include <cmath> ...
- bootstrap课程5 bootstrap中的组件使用的注意事项是什么
bootstrap课程5 bootstrap中的组件使用的注意事项是什么 一.总结 一句话总结: 1.img-responsive的作用是什么(其实还是要多看手册)? 看起来像width=100%的效 ...
- java学习笔记之基础语法(二)
1.数组: 概念:同一种类型数据的集合,其实,数组就是一个容器 优点:可以方便的对其进行操作,编号从0开始,方便操作这些元素. 2,数组的格式 元素类型[]数组名=new 元素类型[数组元素个数]: ...
- TF卡电压 SD卡引脚
//////////////////////////////////////////////////////////////////////////////////////////////////// ...
- 4、基于JZ2440之编写测试代码处理(处理图片识别人脸)
1.代码如下: void detectAndDisplay(Mat image) { CascadeClassifier ccf; //创建脸部对象 //ccf.load(xmlPath); //导入 ...