1212
1313% % API
1414-export ([start_link /0 ,
15+ maybe_kill_epmd /0 ,
1516 apply_config /1 ,
1617 change_external_listeners /2 ,
1718 ensure_tls_dist_started /1 ]).
2526-include_lib (" kernel/include/net_address.hrl" ).
2627-include (" ns_common.hrl" ).
2728
29+ -define (CAN_KILL_EPMD , ? get_param (can_kill_epmd , true )).
30+
2831% %%===================================================================
2932% %% API
3033% %%===================================================================
@@ -49,6 +52,10 @@ init([]) ->
4952 ServerName = ? MODULE ,
5053 register (ServerName , self ()),
5154 ensure_ns_config_settings_in_order (),
55+ % % We choose to kill epmd at startup if required. This is mainly required
56+ % % for windows as for unix systems epmd will not be started because of
57+ % % no_epmd file.
58+ misc :is_windows () andalso maybe_kill_epmd (),
5259 proc_lib :init_ack ({ok , self ()}),
5360 case misc :consult_marker (update_marker_path ()) of
5461 {ok , [Cmd ]} ->
@@ -371,6 +378,59 @@ check_nodename_resolvable(Node, AFamily) ->
371378 {error , iolist_to_binary (M )}
372379 end .
373380
381+ epmd_executable () ->
382+ case misc :is_windows () of
383+ true ->
384+ % % Epmd doesn't exist in the bin path for windows so we pass the
385+ % % erts_bin_path env to point us to it.
386+ {ok , ERTSPath } = application :get_env (ns_server ,
387+ erts_bin_path ),
388+ filename :join (ERTSPath , " epmd.exe" );
389+ false ->
390+ path_config :component_path (bin , " epmd" )
391+ end .
392+
393+ kill_epmd () ->
394+ Path = epmd_executable (),
395+ Port = erlang :open_port ({spawn_executable , Path },
396+ [stderr_to_stdout , binary ,
397+ stream , exit_status , hide ,
398+ {args , [" -kill" ]}]),
399+ {ExitStatus , Output } = wait_for_exit (Port , []),
400+ case ExitStatus of
401+ 0 ->
402+ ok ;
403+ _ ->
404+ ? log_error (" Failed to kill epmd: ~p " , [{ExitStatus , Output }]),
405+ error
406+ end .
407+
408+ wait_for_exit (Port , Output ) ->
409+ receive
410+ {Port , {data , Data }} ->
411+ wait_for_exit (Port , Output ++ binary_to_list (Data ));
412+ {Port , {exit_status , Status }} ->
413+ {Status , Output }
414+ end .
415+
416+ maybe_kill_epmd () ->
417+ NoEpmdFile = path_config :component_path (data , " no_epmd" ),
418+ case ? CAN_KILL_EPMD andalso cluster_compat_mode :is_cluster_70 () andalso
419+ (misc :get_afamily_only () orelse misc :disable_non_ssl_ports ()) of
420+ true ->
421+ try
422+ misc :create_marker (NoEpmdFile ),
423+ ? log_info (" Killing epmd ..." ),
424+ kill_epmd ()
425+ catch
426+ T :E :S ->
427+ ? log_error (" Exception while killing epmd ~p " , [{T , E , S }])
428+ end ;
429+ false ->
430+ file :delete (NoEpmdFile ),
431+ ok
432+ end .
433+
374434% % This function is needed in two cases:
375435% % - migration for address family settings to 6.5
376436% % - allow manual changes in dist_cfg file
0 commit comments