esockd_connection_sup不是一个严格的supervisor。它只是一个gen_server。这是因为他的特殊性决定的。

start_link(Options, MFArgs, Logger) ->

gen_server:start_link(?MODULE, [Options, MFArgs, Logger], []).

supervisor中的必须有重启策略,如果没有在spec中填写默认就是one_for_one。这几种重启策略都会重启子进程。

但是对于sockt连接,断了就是断了,不应该重启的。因此不需要什么重启策略。那么supervisor怎么也得有个监督关系啊,

需要的是当子进程挂了的时候,supervisor要收到消息。

那他是怎么启动子进程(socket连接)的呢?

在esockd_connection_sup.erl中,Conn:start_link(MFArgs)函数调用 emqttd_client:start_link/2 来创建client进程。

esockd_connection_sup.erl:

start_connection(Sup, Mod, Sock, SockFun) ->

case call(Sup, {start_connection, Sock, SockFun}) of

{ok, Pid, Conn} ->

% transfer controlling from acceptor to connection

Mod:controlling_process(Sock, Pid),

Conn:go(Pid),

{ok, Pid};

{error, Error} ->

{error, Error}

end.

handle_call({start_connection, Sock, SockFun}, _From,

State = #state{conn_opts = ConnOpts, mfargs = MFArgs,

curr_clients = Count, access_rules = Rules}) ->

case inet:peername(Sock) of

{ok, {Addr, _Port}} ->

case allowed(Addr, Rules) of

true ->

Conn = esockd_connection:new(Sock, SockFun, ConnOpts),

case catch Conn:start_link(MFArgs) of

{ok, Pid} when is_pid(Pid) ->

...

emqttd_client:start_link/2 调用 proc_lib:spawn_link/3 来启动进程:

emqttd_client.erl:

start_link(Conn, Env) ->

{ok, proc_lib:spawn_link(?MODULE, init, [[Conn, Env]])}.

为什么这里要使用proc_link:spwan_link/3来启动连接进程呢?因为这个函数最终是调用erlang:spawn_link来启动,并自动创建link。

该函数和erlang:start_link的方式区别是spawn_link属于异步启动进程。一调用就会返回子进程ID。

他的用处在emqttd_client:init中看到:

init([Conn0, Env]) ->

{ok, Conn} = Conn0:wait(),

case Conn:peername() of

{ok, Peername} -> do_init(Conn, Env, Peername);

{error, enotconn} -> Conn:fast_close(),

exit(normal);

{error, Reason} -> Conn:fast_close(),

exit({shutdown, Reason})

end.

这里的 Conn0:wait():

esockd_connection.erl:

wait(Conn = ?CONN_MOD) ->

receive {go, Conn} -> upgrade(Conn) end.

使用 receive 来接受消息{go, Conn}。如果emqttd_client:start_link中不使用spawn_link来启动进程,那么在 init 中就会卡死。

这样在 esockd_connection_sup:start_connection(Sup, Mod, Sock, SockFun) 中,Conn:go()就不会被执行。因此出现wait()一直

等待go()发出消息。

如果使用spawn_link就会直接返回,init中执行wait,go被执行后发出消息由wait收到,然后才执行do_init(Conn, Env, Peername)

函数。

另外,esockd_connection_sup 中和子进程link之后,相互都会收到对方 exit 的消息,这样可能 esockd_connection_sup 可能会因为

子进程挂掉而挂掉,为了避免这种情况,esockd_connection_sup 启动的时候在init中设置 process_flag(trap_exit, true), 这样

可以将子进程发送的 exit 消息转化为消息{'EXIT', Pid, Reason},从而避免 esockd_connection_sup 被牵连而挂掉。

handle_info({'EXIT', Pid, Reason}, State = #state{curr_clients = Count, logger = Logger}) ->

...

总结一下:只要理解了spawn_link的异步方式就可以理解wait和go了。

emqttd 不是内部或外部命令_emqttd随笔相关推荐

  1. jdk12‘javac‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    前言: 安装JDK12遇到的问题以及学习过程, 我第一次用网上的安装办法,下载EXE后,配置好三个环境变量后运行,不行. 解决过程: 问题1:安装后javac命令运行时报错 jdk12'javac' ...

  2. vue 不是内部或外部命令,也不是可运行的程序 或批处理文件

    vue 安装 vue-cli 成功之后 控制台查看vue的版本 提示 vue 不是内部或外部命令,也不是可运行的程序 或批处理文件 我的问题 就环境变量没有配置 下面以window 10 系统说下我的 ...

  3. 安装需要的第三方库时,命令行输入pip提示不是内部或外部命令

    简介 在做Python开发时,安装需要的第三方库时,大多数人喜欢选择在命令行用pip进行安装. 然而有时敲入pip命令会提示'pip'不是内部或外部命令..如图: 解决办法 1.在python安装目录 ...

  4. ‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序

    从github上面下载了一个项目,在本地执行 但是一直出现这样的错误 vue-cli-service 不是内部命令 > vue-cli-service serve'vue-cli-service ...

  5. wsimport 不是内部或外部命令,也不是可运行的程序或批处理文件

    我的是windows10系统,在生成webservice代码的时候提示这个错误: wsimport 不是内部或外部命令,也不是可运行的程序或批处理文件 看到网上各种帖子,各位大神都是认为Jdk的环境部 ...

  6. 不是内部或外部命令 windows10 执行 linux命令

    不是内部或外部命令 windows10 执行 linux命令 打开 PowerShell 输入linux命令

  7. “adb不是内部或外部命令,也不是可执行的应用程序”错误原因及解决方法

    用SQLite时,可能会出现这样的错误. 原因可能是环境变量PATH没有配置或配置不正确.应该把adb.exe 所在目录加入到PATH环境变量.例如:C:\Program Files\android- ...

  8. win10配置java环境变量,解决javac不是内部或外部命令等问题

    win10配置java环境变量,解决javac不是内部或外部命令等问题 * 1,首先进入环境变量页面  2,在系统变量下面配置 JAVA_HOME:你自己的jdk的路径 CLASSPATH= .;%J ...

  9. android的dmtracedump工具生成trace文件图片 'dot' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    http://jingyan.baidu.com/article/c910274bfa6c1fcd361d2df7.html http://www.cnblogs.com/albert1017/p/3 ...

最新文章

  1. 刻意练习:LeetCode实战 -- 不同的二叉搜索树
  2. %config InlineBackend.figure_format=svg#矢量图设置
  3. 从CIO视角出发审视云环境下的安全议题
  4. 分不清的InputStream和OutputStream
  5. 计算机应用基础期末考试电大,(电大)期末考试2017年广播电视大学网考《计算机应用基础》重点复习题目汇总版(理论题及操作题)...
  6. 利用php-console和Chrome开发者工具实现PHP应用的printf
  7. php 递归栏目名叠加,thinkPHP实现递归循环栏目并按照树形结构无限极输出的方法,thinkphp递归...
  8. 区块链未来发展三大关键词,华为云如何见招拆招?
  9. 1.5_insert_sort_插入排序
  10. 跟随我在oracle学习php(42)
  11. 精通JavaScript+jQuery:100%动态网页设计密码 中文PDF扫描版
  12. GO 语言的GOROOT 和GOPATH
  13. [渝粤教育] 四川大学 土木工程概论 参考 资料
  14. Java软件工程师面试常见问题集锦之一
  15. 数控技能大赛计算机程序设计员,第八届全国数控技能大赛决赛获奖名单
  16. Win11笔记本耗电大怎么解决?Win11耗电快怎么办?
  17. 获取当前日期的上一个月和后三个月。
  18. 中山大学计算机学院交换生去国外,中山大学取消与伯克利大学交换生项目
  19. 【论文笔记】Bullseye Polytope: A Scalable Clean-Label Poisoning Attack with Improved Transferability
  20. SpringCloudAlibaba看的某马视频笔记

热门文章

  1. 微信公众号之开发者工具
  2. Google Earth Engine——全球建筑物GlobalMLBuildingFootprints矢量集合下载
  3. 三重积分与高斯散度定理
  4. severlet技术概念 基础
  5. Socket模拟HTTP协议之火车票购票软件
  6. form 表单提交的时候 提示那些没有填写 ---以及定位到报错位置--表单报错
  7. 文献管理与信息分析课程分享
  8. 华为手机无法安装apk
  9. android push sdk6,JPush SDK 华为通道集成指南
  10. android app 多国语语言快速翻译