-
Notifications
You must be signed in to change notification settings - Fork 9
Applications_and_OTP_startup
It seems that the whole BEAM VM is started by running init:boot that:
- doesn't return
- Parses command line args
- Starts a process registered as
init - Reads and interprets the boot script (See below)
I couldn't find any explicit call to init:boot in code, the docs only say:
This function is called when the emulator is started and coordinates system startup.
References:
AtomVM is missing boot script support. https://www.erlang.org/doc/system/system_principles.html#boot-scripts.
In short, this is BEAMs entrypoint, starting what's needed to start new apps
A default one in both binary (.boot) and textual (.script) is present next to erlang binary. https://www.erlang.org/doc/system/system_principles.html#default-boot-scripts
Contents of ./bin/start.script:
1 │ %% coding: utf-8
2 │ {script,
3 │ {"Erlang/OTP","26"},
4 │ [{preLoaded,
5 │ [atomics,counters,erl_init,erl_prim_loader,erl_tracer,erlang,
6 │ erts_code_purger,erts_dirty_process_signal_handler,erts_internal,
7 │ erts_literal_area_collector,init,persistent_term,prim_buffer,
8 │ prim_eval,prim_file,prim_inet,prim_net,prim_socket,prim_zip,
9 │ socket_registry,zlib]},
10 │ {progress,preloaded},
11 │ {path,["$ROOT/lib/kernel-9.0.2/ebin","$ROOT/lib/stdlib-5.0.2/ebin"]},
12 │ {primLoad,
13 │ [error_handler,application,application_controller,application_master,
14 │ code,code_server,erl_eval,erl_lint,erl_parse,error_logger,ets,file,
15 │ filename,file_server,file_io_server,gen,gen_event,gen_server,heart,
16 │ kernel,logger,logger_filters,logger_server,logger_backend,
17 │ logger_config,logger_simple_h,lists,proc_lib,supervisor]},
18 │ {kernel_load_completed},
19 │ {progress,kernel_load_completed},
20 │ {path,["$ROOT/lib/kernel-9.0.2/ebin"]},
21 │ {primLoad,
22 │ [application_starter,auth,disk_log,disk_log_1,disk_log_server,
23 │ disk_log_sup,dist_ac,dist_util,erl_boot_server,erl_compile_server,
24 │ erl_ddll,erl_distribution,erl_epmd,erl_erts_errors,
25 │ erl_kernel_errors,erl_reply,erl_signal_handler,erpc,erts_debug,
26 │ gen_sctp,gen_tcp,gen_tcp_socket,gen_udp,gen_udp_socket,global,
27 │ global_group,global_search,group,group_history,inet,inet6_sctp,
28 │ inet6_tcp,inet6_tcp_dist,inet6_udp,inet_config,inet_db,inet_dns,
29 │ inet_epmd_dist,inet_epmd_socket,inet_gethost_native,inet_hosts,
30 │ inet_parse,inet_res,inet_sctp,inet_tcp,inet_tcp_dist,inet_udp,
31 │ kernel_config,kernel_refc,local_tcp,local_udp,logger_disk_log_h,
32 │ logger_formatter,logger_h_common,logger_handler_watcher,logger_olp,
33 │ logger_proxy,logger_std_h,logger_sup,net,net_adm,net_kernel,os,pg,
34 │ pg2,prim_tty,ram_file,raw_file_io,raw_file_io_compressed,
35 │ raw_file_io_deflate,raw_file_io_delayed,raw_file_io_inflate,
36 │ raw_file_io_list,rpc,seq_trace,socket,standard_error,user_drv,
37 │ user_sup,wrap_log_reader]},
38 │ {path,["$ROOT/lib/stdlib-5.0.2/ebin"]},
39 │ {primLoad,
40 │ [argparse,array,base64,beam_lib,binary,c,calendar,dets,dets_server,
41 │ dets_sup,dets_utils,dets_v9,dict,digraph,digraph_utils,edlin,
42 │ edlin_context,edlin_expand,edlin_type_suggestion,epp,
43 │ erl_abstract_code,erl_anno,erl_bits,erl_compile,erl_error,
44 │ erl_expand_records,erl_features,erl_internal,erl_posix_msg,erl_pp,
45 │ erl_scan,erl_stdlib_errors,erl_tar,error_logger_file_h,
46 │ error_logger_tty_h,escript,eval_bits,file_sorter,filelib,gb_sets,
47 │ gb_trees,gen_fsm,gen_statem,io,io_lib,io_lib_format,io_lib_fread,
48 │ io_lib_pretty,log_mf_h,maps,math,ms_transform,orddict,ordsets,
49 │ otp_internal,peer,pool,proplists,qlc,qlc_pt,queue,rand,random,re,
50 │ sets,shell,shell_default,shell_docs,slave,sofs,string,
51 │ supervisor_bridge,sys,timer,unicode,unicode_util,uri_string,
52 │ win32reg,zip]},
53 │ {progress,modules_loaded},
54 │ {path,["$ROOT/lib/kernel-9.0.2/ebin","$ROOT/lib/stdlib-5.0.2/ebin"]},
55 │ {kernelProcess,heart,{heart,start,[]}},
56 │ {kernelProcess,logger,{logger_server,start_link,[]}},
57 │ {kernelProcess,application_controller,
58 │ {application_controller,start,
59 │ [{application,kernel,
60 │ [{description,"ERTS CXC 138 10"},
61 │ {vsn,"9.0.2"},
62 │ {id,[]},
63 │ {modules,
64 │ [application,application_controller,application_master,
65 │ application_starter,auth,code,code_server,dist_util,
66 │ erl_boot_server,erl_compile_server,erl_distribution,
67 │ erl_erts_errors,erl_reply,erl_kernel_errors,
68 │ erl_signal_handler,erpc,error_handler,error_logger,
69 │ file,file_server,file_io_server,global,global_group,
70 │ global_search,group,group_history,heart,inet6_tcp,
71 │ inet6_tcp_dist,inet6_udp,inet6_sctp,inet_config,
72 │ inet_epmd_dist,inet_epmd_socket,inet_hosts,
73 │ inet_gethost_native,inet_tcp_dist,kernel,
74 │ kernel_config,kernel_refc,local_tcp,local_udp,logger,
75 │ logger_backend,logger_config,logger_disk_log_h,
76 │ logger_filters,logger_formatter,logger_h_common,
77 │ logger_handler_watcher,logger_olp,logger_proxy,
78 │ logger_server,logger_simple_h,logger_std_h,logger_sup,
79 │ net,net_adm,net_kernel,os,ram_file,rpc,user_drv,
80 │ user_sup,prim_tty,disk_log,disk_log_1,disk_log_server,
81 │ disk_log_sup,dist_ac,erl_ddll,erl_epmd,erts_debug,
82 │ gen_tcp,gen_tcp_socket,gen_udp,gen_udp_socket,
83 │ gen_sctp,inet,inet_db,inet_dns,inet_parse,inet_res,
84 │ inet_tcp,inet_udp,inet_sctp,pg,pg2,raw_file_io,
85 │ raw_file_io_compressed,raw_file_io_deflate,
86 │ raw_file_io_delayed,raw_file_io_inflate,
87 │ raw_file_io_list,seq_trace,socket,standard_error,
88 │ wrap_log_reader]},
89 │ {registered,
90 │ [application_controller,erl_reply,auth,boot_server,
91 │ code_server,disk_log_server,disk_log_sup,
92 │ erl_prim_loader,error_logger,file_server_2,
93 │ fixtable_server,global_group,global_name_server,heart,
94 │ init,kernel_config,kernel_refc,kernel_sup,logger,
95 │ logger_handler_watcher,logger_sup,net_kernel,net_sup,
96 │ rex,user,os_server,ddll_server,erl_epmd,inet_db,pg]},
97 │ {applications,[]},
98 │ {optional_applications,[]},
99 │ {included_applications,[]},
100 │ {env,
101 │ [{logger_level,notice},
102 │ {logger_sasl_compatible,false},
103 │ {net_tickintensity,4},
104 │ {net_ticktime,60},
105 │ {prevent_overlapping_partitions,true},
106 │ {shell_docs_ansi,auto}]},
107 │ {maxT,infinity},
108 │ {maxP,infinity},
109 │ {mod,{kernel,[]}}]}]}},
110 │ {progress,init_kernel_started},
111 │ {apply,
112 │ {application,load,
113 │ [{application,stdlib,
114 │ [{description,"ERTS CXC 138 10"},
115 │ {vsn,"5.0.2"},
116 │ {id,[]},
117 │ {modules,
118 │ [argparse,array,base64,beam_lib,binary,c,calendar,dets,
119 │ dets_server,dets_sup,dets_utils,dets_v9,dict,digraph,
120 │ digraph_utils,edlin,edlin_context,edlin_expand,
121 │ edlin_type_suggestion,epp,eval_bits,erl_abstract_code,
122 │ erl_anno,erl_bits,erl_compile,erl_error,erl_eval,
123 │ erl_expand_records,erl_features,erl_internal,erl_lint,
124 │ erl_parse,erl_posix_msg,erl_pp,erl_scan,
125 │ erl_stdlib_errors,erl_tar,error_logger_file_h,
126 │ error_logger_tty_h,escript,ets,file_sorter,filelib,
127 │ filename,gb_trees,gb_sets,gen,gen_event,gen_fsm,
128 │ gen_server,gen_statem,io,io_lib,io_lib_format,
129 │ io_lib_fread,io_lib_pretty,lists,log_mf_h,maps,math,
130 │ ms_transform,orddict,ordsets,otp_internal,peer,pool,
131 │ proc_lib,proplists,qlc,qlc_pt,queue,rand,random,re,
132 │ sets,shell,shell_default,shell_docs,slave,sofs,string,
133 │ supervisor,supervisor_bridge,sys,timer,unicode,
134 │ unicode_util,uri_string,win32reg,zip]},
135 │ {registered,
136 │ [timer_server,rsh_starter,take_over_monitor,
137 │ pool_master,dets]},
138 │ {applications,[kernel]},
139 │ {optional_applications,[]},
140 │ {included_applications,[]},
141 │ {env,[]},
142 │ {maxT,infinity},
143 │ {maxP,infinity}]}]}},
144 │ {progress,applications_loaded},
145 │ {apply,{application,start_boot,[kernel,permanent]}},
146 │ {apply,{application,start_boot,[stdlib,permanent]}},
147 │ {apply,{c,erlangrc,[]}},
148 │ {progress,started}]}.
This means based on https://www.erlang.org/doc/apps/sasl/script:
- Name = Erlang/OTP, Version = "26"
- List of preloaded modules - no docs (xD) so no idea if it declares or actually preloads them
-
{progress, X}sets status of init, obtainable viainit:get_status/0 - Using
pathandprimLoadmodules ofkernelandstdlibare loaded - Three kernel processes are started:
-
heartby runningheart:start() -
loggerby runninglogger_server:start_link() -
application_controllerby runningapplication_controller:start([{application, kernel, Spec}])whereSpecis a hardcoded specification ofkernelapp
-
- Specification of
stdlibapplication is loaded viaapplication:load(HardcodedSpec) - Call to
application:start_boot(kernel, permament) - Call to
application:start_boot(stdlib, permament) - Call to
c:erlangrc()- loads.erlangresource file
In a Popcorn-patched version of :kernel module, it is a noop. In OTP however,
it starts a whole supervision tree documented here.
Among the missing processes, here are the ones that I investigated due to errors:
-
user_supstartinguserprocess responsible for hanling IO of stadard input/output Some internal functions assumeuserprocess exists and forwardio_requests there, and work incorrectly if it's missing, e.g.application_master -
standard_errorhandlingio_requests tostderr -
logger_supstarting logger-related processes -
file_server_2- handling file IO. Might be called when trying to start an application that doesn't have its spec loaded, resulting in attempt to find proper*.appfile
When application is started, application master process is started, that is a group leader for all the processes of the app. See: https://www.erlang.org/docs/28/system/applications#starting-and-stopping-applications Internally there's an additional process, between App supervisor and application_master https://github.com/erlang/otp/blob/d051172925a5c84b2f21850a188a533f885f201c/lib/kernel/src/application_master.erl#L84