| 
                            
                                  概述在做mongo建连优化时,突然发现打出的包无法启动。有日志如下: 
{"Kernel pid terminated",application_controller,"{application_start_failure,kernel,{{shutdown,{failed_to_start_child,kernel_safe_sup,{on_load_function_failed,fast_pbkdf2}}},{kernel,start,[normal,[]]}}}"}Kernel pid terminated (application_controller) ({application_start_failure,kernel,{{shutdown,{failed_to_start_child,kernel_safe_sup,{on_load_function_failed,fast_pbkdf2}}},{kernel,start,[normal,[]]}}}
 原因是打包机的环境变更,导致: 
	
		
			| 1 2 3 4 5 | root@xxxxx:/srv/apps/xxxxx/lib/fast_pbkdf2-1.0.5/priv# ldd fast_pbkdf2.so         linux-vdso.so.1 =>  (0x00007ffc71bc6000)         libcrypto.so.1.1 => not found         libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faf60b69000)         /lib64/ld-linux-x86-64.so.2 (0x00007faf61139000) |  排查过程
	回滚代码到可启动包代码。重新打包,也无法启动。基本判定是打包机环境变更问题。并找了打包机的管理同学。设可运行包为a,不可运行包为b,对比a, b的差异。a, b包均可在开发环境正常运行。nm 命令对比 a/b 的fast_pbkdf2.so symbols。用 erlang crash viewer 查看 crashdump,无有效信息。打包机管理同学发现回滚mongodb安装后问题修复。 ldd 命令发现真正问题:打包机安装mongodb后,fast_pbkdf2.so link到了libcrypto.so.1.1,而之前是 libcrypto.so.1.0.0,我本地开发环境有libcrypto.so.1.1,故a, b都可运行,而生产容器只有 libcrypto.so.1.0.0,所以运行失败。 代码
OTP-24.1init.erl:1465
 erlang load 失败时,会on_load_function_failed。这里除了load失败的模块,没有携带任何有效信息。 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | run_on_load_handlers([M|Ms], Debug) ->  debug(Debug, {running_on_load_handler,M}),  Fun = fun() ->        Res = erlang:call_on_load_function(M),        exit(Res)    end,  {Pid,Ref} = spawn_monitor(Fun),  receive  {'DOWN',Ref,process,Pid,OnLoadRes} ->      Keep = OnLoadRes =:= ok,      erlang:finish_after_on_load(M, Keep),      case Keep of      false ->          Error = {on_load_function_failed,M},          debug(Debug, Error),          exit(Error);      true ->          debug(Debug, {on_load_handler_returned_ok,M}),          run_on_load_handlers(Ms, Debug)      end  end; run_on_load_handlers([], _) -> ok. |  结论
	erlang 遇到动态库的on_load_function_failed时,从 c/c++ 动态库加载的角度排查。打包应该保持和生产环境一致,可以用同一个docker镜像。 
 |