-
Notifications
You must be signed in to change notification settings - Fork 5
/
building-otp-applications.html
390 lines (293 loc) · 29.4 KB
/
building-otp-applications.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="keywords" content="Erlang, OTP, application, .app file, behaviour, master, controller, supervisor, file, group leader" />
<meta name="description" content="Introduction to the concept of OTP applications. We take previous bits of code and convert them to fit the OTP model for the VM." />
<meta name="google-site-verification" content="mi1UCmFD_2pMLt2jsYHzi_0b6Go9xja8TGllOSoQPVU" />
<link rel="stylesheet" type="text/css" href="static/css/screen.css" media="screen" />
<link rel="stylesheet" type="text/css" href="static/css/sh/shCore.css" media="screen" />
<link rel="stylesheet" type="text/css" href="static/css/sh/shThemeLYSE2.css" media="screen" />
<link rel="stylesheet" type="text/css" href="static/css/print.css" media="print" />
<link href="rss" type="application/rss+xml" rel="alternate" title="LYSE news" />
<link rel="icon" type="image/png" href="favicon.ico" />
<link rel="apple-touch-icon" href="static/img/touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="72x72" href="static/img/touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="114x114" href="static/img/touch-icon-iphone4.png" />
<title>Building OTP Applications | Learn You Some Erlang for Great Good!</title>
</head>
<body>
<div id="wrapper">
<div id="header">
<h1>Learn you some Erlang</h1>
<span>for great good!</span>
</div> <!-- header -->
<div id="menu">
<ul>
<li><a href="content.html" title="Home">Home</a></li>
<li><a href="faq.html" title="Frequently Asked Questions">FAQ</a></li>
<li><a href="rss" title="Latest News">RSS</a></li>
<li><a href="static/erlang/learn-you-some-erlang.zip" title="Source Code">Code</a></li>
</ul>
</div><!-- menu -->
<div id="content">
<div class="noscript"><noscript>Hey there, it appears your Javascript is disabled. That's fine, the site works without it. However, you might prefer reading it with syntax highlighting, which requires Javascript!</noscript></div>
<h2>Building OTP Applications</h2>
<h3><a class="section" name="why-would-i-want-that">Why Would I Want That?</a></h3>
<img class="right" src="static/img/construction.png" width="225" height="224" alt="A construction sign with a squid holdin a shovel, rather than a man doing so" />
<p>After seeing our whole application's supervision tree start at once with a simple function call, we might wonder why we would want to make things more complicated than they already are. The concepts behind supervision trees are a bit complex and I could see myself just starting all of these trees and subtrees manually with a script when the system is first set up. Then after that, I would be free to go outside and try to find clouds that look like animals for the rest of the afternoon.</p>
<p>This is entirely true, yes. This is an acceptable way to do things (especially the part about clouds, because these days everything is about cloud computing). However, as for most abstractions made by programmers and engineers, OTP applications are the result of many ad-hoc systems being generalised and made clean. If you were to make an array of scripts and commands to start your supervision trees as described above, and that other developers you work with had their own, you'd quickly run into massive issues. Then someone would ask something like "Wouldn't it be nice if everyone used the same kind of system to start everything? And wouldn't it even be nicer if they all had the same kind of application structure?"</p>
<p>OTP applications attempt to solve this exact type of problem. They give a directory structure, a way to handle configurations, a way to handle dependencies, create environment variables and configuration, ways to start and stop applications, and a lot of safe control in detecting conflicts and handling live upgrades them without shutting your applications down.</p>
<p>So unless you don't want these aspects (nor the niceties they give, like consistent structures and tools developed for it), this chapter should be of some interest to you.</p>
<h3><a class="section" name="my-other-car-is-a-pool">My Other Car is a Pool</a></h3>
<p>We're going to reuse the <code>ppool</code> application we wrote for last chapter and turn it into a real OTP application.</p>
<p>The first step in doing so is to copy all the <code>ppool</code> related files into a neat directory structure:</p>
<pre class="expand">
ebin/
include/
priv/
src/
- ppool.erl
- ppool_sup.erl
- ppool_supersup.erl
- ppool_worker_sup.erl
- ppool_serv.erl
- ppool_nagger.erl
test/
- ppool_tests.erl
</pre>
<p>Most directories will for now remain empty. As explained in the <a class="chapter" href="designing-a-concurrent-application.html#lay-them-foundation">Designing a Concurrent Application</a> chapter, the <code>ebin/</code> directory will hold compiled files, the <code>include/</code> directory will contain Erlang header (<code>.hrl</code>) files, <code>priv/</code> will hold executables, other programs, and various specific files needed for the application to work and <code>src/</code> will hold the Erlang source files you will need.</p>
<img class="left" src="static/img/carpool.png" width="307" height="218" alt="A pool with wheels and an exhaust pipe" />
<p>You'll note that I added a <code>test/</code> directory just for the test file I had before. The reason for this is that tests are somewhat common, but you don't necessarily want them distributed as part of your application — you just need them when developing your code and justifying yourself to your manager ("tests pass, I don't understand why the app killed people"). Other directories like that end up being added as required, depending on the case. One example is the <code>doc/</code> directory, added whenever you have <a class="docs" href="http://www.erlang.org/doc/apps/edoc/chapter.html">EDoc</a> documentation to add to your application.</p>
<p>The four basic directories to have are <code>ebin/</code>, <code>include/</code>, <code>priv/</code> and <code>src/</code> and they'll be common to pretty much every OTP application you get, although only <code>ebin/</code> and <code>priv/</code> are going to be exported when real OTP systems are deployed.</p>
<h3><a class="section" name="the-application-resource-file">The Application Resource File</a></h3>
<p>Where do we go from here? Well the first thing to do is to add an application file. This file will tell the Erlang VM what the application is, where it begins and where it ends. This file lives on in the <code>ebin/</code> directory, along with all the compiled modules. </p>
<p>This file is usually named <code><yourapp>.app</code> (in our case <code>ppool.app</code>) and contains a bunch of Erlang terms defining the application in terms the VM can understand (the VM is pretty bad at guessing stuff!)</p>
<div class="note">
<p><strong>Note:</strong> some people prefer to keep this file outside of <code>ebin/</code> and instead have a file named <code><myapp>.app.src</code> as part of <code>src/</code>. Whatever build system they use then copies this file over to <code>ebin/</code> or even generates one in order to keep everything clean.</p>
</div>
<p>The basic structure of the application file is simply:</p>
<h4>{application, ApplicationName, Properties}.</h4>
<p>Where <var>ApplicationName</var> is an atom and <var>Properties</var> is a list of <code>{Key, Value}</code> tuples describing the application. They're used by OTP to figure out what your application does and whatnot, they're all optional, but might always be useful to carry around and necessary for some tools. In fact, we'll only look at a subset of them for now and introduce the others as we need them:</p>
<h4>{description, "Some description of your application"}</h4>
<p>This gives the system a short description of what the application is. The field is optional and defaults to an empty string. I would suggest always defining a description, if only because it makes things easier to read.</p>
<h4>{vsn, "1.2.3"}</h4>
<p>Tells what's the version of your application. The string takes any format you want. It's usually a good idea to stick to a scheme of the form <code><major>.<minor>.<patch></code> or something like that. When we get to tools to help with upgrades and downgrades, the string is used to identify your application's version.</p>
<h4>{modules, ModuleList}</h4>
<p>Contains a list of all the modules that your application introduces to the system. A module always belongs to at most one application and can not be present in two applications' app files at once. This list lets the system and tools look at dependencies of your application, making sure everything is where it needs to be and that you have no conflicts with other applications already loaded in the system. If you're using a standard OTP structure and are using a build tool like <em>rebar</em>, this is handled for you.</p>
<h4>{registered, AtomList}</h4>
<p>Contains a list of all the names registered by the application. This lets OTP know when there will be name clashes when you try to bundle a bunch of applications together, but is entirely based on trusting the developers to give good data. We all know this isn't always the case, so blind faith shouldn't be used in this case.</p>
<h4>{env, [{Key, Val}]}</h4>
<p>This is a list of key/values that can be used as a configuration for your application. They can be obtained at run time by calling <code>application:get_env(Key)</code> or <code>application:get_env(AppName, Key)</code>. The first one will try to find the value in the application file of whatever application you are in at the moment of the call, the second allows you to specify an application in particular. This stuff can be overwritten as required (either at boot time or by using <code><a class="docs" href="http://erldocs.com/17.3/kernel/application.html#set_env/3">application:set_env/3-4</a></code>.</p>
<p>All in all this is a pretty useful place to store configuration data rather than having a bunch of config files to read in whatever format, without really knowing where to store them and whatnot. People often tend to roll their own system over it anyway, given not everyone is a fan of using Erlang syntax in configuration files.</p>
<h4>{maxT, Milliseconds}</h4>
<p>This is the maximum time that the application can run, after which it will be shut down. This is a rather rarely used item and <var>Milliseconds</var> defaults to <code>infinity</code>, so you often don't need to bother with this one at all.</p>
<h4>{applications, AtomList}</h4>
<p>A list of applications on which yours depends. The application system of Erlang will make sure they were loaded and/or started before allowing yours to do so. All applications depend at least on <code>kernel</code> and <code>stdlib</code>, but if your application were to depend on <code>ppool</code> being started, then you should add <code>ppool</code> to the list.</p>
<div class="note">
<p><strong>Note:</strong> yes, the standard library and the VM's kernel are applications themselves, which means that Erlang is a language used to build OTP, but whose runtime environment depends on OTP to work. It's circular. This gives you some idea of why the language is officially named 'Erlang/OTP'.</p>
</div>
<h4>{mod, {CallbackMod, Args}}</h4>
<p>Defines a callback module for the application, using the application behaviour (which we will see in the <a class="chapter" href="building-otp-applications.html#the-application-behaviour">next section</a>). This tells OTP that when starting your application, it should call <code>CallbackMod:start(normal, Args)</code>. This function's return value will be used when OTP will call <code>CallbackMod:stop(StartReturn)</code> when stopping your application. People will tend to name <var>CallbackMod</var> after their application.</p>
<p>And this covers most of what we might need for now (and for most applications you'll ever write).</p>
<h4>Converting the Pool</h4>
<p>How about we put this into practice? We'll turn the <code>ppool</code> set of processes from last chapter into a basic OTP application. The first step for this is to redistribute everything under the right directory structure. Just create five directories and distribute the files as follows:</p>
<pre class="expand">
ebin/
include/
priv/
src/
- ppool.erl
- ppool_serv.erl
- ppool_sup.erl
- ppool_supersup.erl
- ppool_worker_sup.erl
test/
- ppool_tests.erl
- ppool_nagger.erl
</pre>
<p>You'll notice I moved the <code>ppool_nagger</code> to the test directory. This is for a good reason — it was not much more than a demo case and would have nothing to do with our application, but is still necessary for the tests. We can actually try it later on once the app has all been packaged so we can make sure everything still works, but for the moment it's kind of useless.</p>
<p>We'll add an Emakefile (appropriately named <code>Emakefile</code>, placed in the app's base directory) to help us compile and run things later on:</p>
<pre class="brush:erl">
{"src/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
{"test/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
</pre>
<p>This just tells the compiler to include <code>debug_info</code> for all files in <code>src/</code> and <code>test/</code>, tells it to go look in the <code>include/</code> directory (if it's ever needed) and then shove the files up its <code>ebin/</code> directory.</p>
<p>Speaking of which, let's add the <a class="source" href="static/erlang/ppool-1.0/ebin/ppool.app">app file</a> in the <code>ebin/</code> directory:</p>
<pre class="brush:erl">
{application, ppool,
[{vsn, "1.0.0"},
{modules, [ppool, ppool_serv, ppool_sup, ppool_supersup, ppool_worker_sup]},
{registered, [ppool]},
{mod, {ppool, []}}
]}.
</pre>
<p>This one only contains fields we find necessary; <code>env</code>, <code>maxT</code> and <code>applications</code> are not used. We now need to change how the callback module (<code>ppool</code>) works. How do we do that exactly?</p>
<p>First, let's see the application behaviour.</p>
<div class="note">
<p><strong>Note:</strong> even though all applications depend on the <code>kernel</code> and the <code>stdlib</code> applications, I haven't included them. <code>ppool</code> will still work because starting the Erlang VM starts these applications automatically. You might feel like adding them for the sake of expliciteness, but there's no <em>need</em> for it right now.</p>
</div>
<img class="center" src="static/img/indiana.gif" width="308" height="215" alt="Parody of Indiana Jones' scene where he substitutes a treasure for a fake weight. The piece of gold has 'generic' written on it, and the fake weight has 'specific' on it" />
<h3><a class="section" name="the-application-behaviour">The Application Behaviour</a></h3>
<p>As for most OTP abstractions we've seen, what we want is a pre-built implementation. Erlang programmers are not happy with design patterns as a convention, they want a solid abstraction for them. This gives us a behaviour for applications. Remember that behaviours are always about splitting generic code away from specific code. They denote the idea that your specific code gives up its own execution flow and inserts itself as a bunch of callbacks to be used by the generic code. In simpler words, behaviours handle the boring parts while you connect the dots. In the case of applications, this generic part is quite complex and not nearly as simple as other behaviours.</p>
<p>Whenever the VM first starts up, a process called the <em>application controller</em> is started (with the name <code>application_controller</code>). It starts all other applications and sits on top of most of them. In fact, you could say the application controller acts a bit like a supervisor for all applications. We'll see what kind of supervision strategies there are in the <a class="chapter" href="building-otp-applications.html#from-chaos-to-application">From Chaos to Application</a> section.</p>
<div class="note">
<p><strong>Note:</strong> the Application Controller technically doesn't sit over all the applications. One exception is the kernel application, which itself starts a process named <code>user</code>. The <code>user</code> process in fact acts as a group leader to the application controller and the kernel application thus needs some special treatment. We don't have to care about this, but I felt like it should be included for the sake of precision.</p>
<p>In Erlang, the IO system depends on a concept called a <em>group leader</em>. The group leader represents standard input and output and is inherited by all processes. There is a hidden <a class="docs" href="http://erlang.org/doc/apps/stdlib/io_protocol.html">IO protocol</a> that the group leader and any process calling IO functions communicate with. The group leader then takes the responsibility of forwarding these messages to whatever input/output channels there are, weaving some magic that doesn't concern us within the confines of this text.</p>
</div>
<p>Anyway, when someone decides they want to start an application, the application controller (often noted <em>AC</em> in OTP parlance) starts an <em>application master</em>. The application master is in fact two processes taking charge of each individual application: they set it up and act like a middleman in between your application's top supervisor and the application controller. OTP is a bureaucracy, and we have many layers of middle-management! I won't get into the details of what happens in there as most Erlang developers will never actually need to care about that and very little documentation exists (the code is the documentation). Just know that the application master acts a bit like the app's nanny (well, a pretty insane nanny). It looks over its children and grandchildren, and when things go awry, it goes berserk and terminates its whole family tree. Brutally killing children is a common topic among Erlangers.</p>
<p>An Erlang VM with a bunch of applications might look a bit like this:</p>
<img class="center explanation" src="static/img/application-controller.png" width="593" height="246" alt="The Application controller stands over three application masters (in this graphic, in real life it has many more), which each stand on top of a supervisor process" />
<p>Up to now, we were still looking at the generic part of the behaviour, but what about the specific stuff? After all, this is all we actually have to program. Well the application callback module requires very few functions to be functional: <code>start/2</code> and <code>stop/1</code>.</p>
<p>The first one takes the form <code>YourMod:start(Type, Args)</code>. For now, the <var>Type</var> will always be <code>normal</code> (the other possibilities accepted have to do with distributed applications, which we'll see at a later point). <var>Args</var> is what is coming from your app file. The function initialises everything for your app and only needs to return the Pid of the application's top-level supervisor in one of the two following forms: <code>{ok, Pid}</code> or <code>{ok, Pid, SomeState}</code>. If you don't return <var>SomeState</var>, it simply defaults to <code>[]</code>.</p>
<p>The <code>stop/1</code> function takes the state returned by <code>start/2</code> as an argument. It runs after the application is done running and only does the necessary cleanup.</p>
<p>That's it. A huge generic part, a tiny specific one. Be thankful for that, because you wouldn't want to write the rest of things too often (just look at the source if you feel like it!) There are a few more functions that you can optionally use to have more control over the application, but we don't need them for now. This means we can move forward with our <code>ppool</code> application!</p>
<h3><a class="section" name="from-chaos-to-application">From Chaos to Application</a></h3>
<p>We have the app file and a general idea of how applications work. Two simple callbacks. Opening <a class="source" href="static/erlang/ppool-1.0/src/ppool.erl" title="this is the resulting file">ppool.erl</a>, we change the following lines:</p>
<pre class="brush:erl">
-export([start_link/0, stop/0, start_pool/3,
run/2, sync_queue/2, async_queue/2, stop_pool/1]).
start_link() ->
ppool_supersup:start_link().
stop() ->
ppool_supersup:stop().
</pre>
<p>To the following ones instead:</p>
<pre class="brush:erl">
-behaviour(application).
-export([start/2, stop/1, start_pool/3,
run/2, sync_queue/2, async_queue/2, stop_pool/1]).
start(normal, _Args) ->
ppool_supersup:start_link().
stop(_State) ->
ok.
</pre>
<p>We can then make sure the tests are still valid. Pick the old <a class="source" href="static/erlang/ppool-1.0/test/ppool_tests.erl" title="this is the resulting file">ppool_tests.erl</a> file (I wrote it for the previous chapter and am bringing it back here) and replace the single call to <code>ppool:start_link/0</code> to <code>application:start(ppool)</code> as follows:</p>
<pre class="brush:erl">
find_unique_name() ->
application:start(ppool),
Name = list_to_atom(lists:flatten(io_lib:format("~p",[now()]))),
?assertEqual(undefined, whereis(Name)),
Name.
</pre>
<p>You should also take the time to remove <code>stop/0</code> from <a class="source" href="static/erlang/ppool-1.0/src/ppool_supersup.erl"><code>ppool_supersup</code></a> (and remove the export), because the OTP application tools will take care of that for us.</p>
<p>We can finally recompile the code and run all the tests to make sure everything still works (we'll see how that <em>eunit</em> thing works later on, don't worry):</p>
<pre class="brush:eshell">
$ erl -make
Recompile: src/ppool_worker_sup
Recompile: src/ppool_supersup
...
$ erl -pa ebin/
...
1> make:all([load]).
Recompile: src/ppool_worker_sup
Recompile: src/ppool_supersup
Recompile: src/ppool_sup
Recompile: src/ppool_serv
Recompile: src/ppool
Recompile: test/ppool_tests
Recompile: test/ppool_nagger
up_to_date
2> eunit:test(ppool_tests).
All 14 tests passed.
ok
</pre>
<p>The tests take a while to run due to <code>timer:sleep(X)</code> being used to synchronise everything in a few places, but it should tell you everything works, as shown above. Good news, our app is healthy.</p>
<p>We can now study the wonders of OTP applications by using our new awesome callbacks:</p>
<pre class="brush:eshell">
3> application:start(ppool).
ok
4> ppool:start_pool(nag, 2, {ppool_nagger, start_link, []}).
{ok,<0.142.0>}
5> ppool:run(nag, [make_ref(), 500, 10, self()]).
{ok,<0.146.0>}
6> ppool:run(nag, [make_ref(), 500, 10, self()]).
{ok,<0.148.0>}
7> ppool:run(nag, [make_ref(), 500, 10, self()]).
noalloc
9> flush().
Shell got {<0.146.0>,#Ref<0.0.0.625>}
Shell got {<0.148.0>,#Ref<0.0.0.632>}
...
received down msg
received down msg
</pre>
<p>The magic command here is <code>application:start(ppool)</code>. This tells the application controller to launch our ppool application. It starts the <code>ppool_supersup</code> supervisor and from that point on, everything can be used as normal. We can see all the applications currently running by calling <code>application:which_applications()</code>:</p>
<pre class="brush:eshell">
10> application:which_applications().
[{ppool,[],"1.0.0"},
{stdlib,"ERTS CXC 138 10","1.17.4"},
{kernel,"ERTS CXC 138 10","2.14.4"}]
</pre>
<p>What a surprise, <code>ppool</code> is running. As mentioned earlier, we can see that all applications depend on <code>kernel</code> and <code>stdlib</code>, which are both running. If we want to close the pool:</p>
<pre class="brush:eshell">
11> application:stop(ppool).
=INFO REPORT==== DD-MM-YYYY::23:14:50 ===
application: ppool
exited: stopped
type: temporary
ok
</pre>
<p>And it is done. You should notice that we now get a clean shutdown with a little informative report rather than the messy <samp>** exception exit: killed</samp> from last chapter.</p>
<div class="note">
<p><strong>Note:</strong> You'll sometimes see people do something like <code>MyApp:start(...)</code> instead of <code>application:start(MyApp)</code>. While this works for testing purposes, it's ruining a lot of the advantages of actually having an application: it's no longer part of the VM's supervision tree, can not access its environment variables, will not check dependencies before being started, etc. Try to stick to <code>application:start/1</code> if possible.</p>
</div>
<p>Look at this! What's that thing about our app being <em>temporary</em>? We write Erlang and OTP stuff because it's supposed to run forever, not just for a while! How dare the VM say this? The secret is that we can give different arguments to <code>application:start</code>. Depending on the arguments, the VM will react differently to termination of one of its applications. In some cases, the VM will be a loving beast ready to die for its children. In other cases, it's rather a cold heartless and pragmatic machine willing to tolerate many of its children dying for the survival of its species.</p>
<dl>
<dt>Application started with: <code>application:start(AppName, temporary)</code></dt>
<dd>Ends normally: Nothing special happens, the application has stopped.</dd>
<dd>Ends abnormally: The error is reported, and the application terminates without restarting.</dd>
<dt>Application started with: <code>application:start(AppName, transient)</code></dt>
<dd>Ends normally: Nothing special happens, the application has stopped.</dd>
<dd>Ends abnormally: The error is reported, all the other applications are stopped and the VM shuts down.</dd>
<dt>Application started with: <code>application:start(AppName, permanent)</code></dt>
<dd>Ends normally: All other applications are terminated and the VM shuts down.</dd>
<dd>Ends abnormally: Same; all applications are terminated, the VM shuts down.</dd>
</dl>
<p>You can see something new in the supervision strategies when it comes to applications. No longer will the VM try to save you. At this point, something has had to go very, very wrong for it to go up the whole supervision tree of one of its vital applications, enough to crash it. When this does happen, the VM has lost all hope in your program. Given the definition of insanity is to do the same thing all over again while expecting different outcomes each time, the VM prefers to die sanely and just give up. Of course the real reason has to do with something being broken that needs to be fixed, but you catch my drift. Take note that all applications can be terminated by calling <code>application:stop(AppName)</code> without affecting others as if a crash had occurred.</p>
<h3><a class="section" name="library-applications">Library Applications</a></h3>
<p>What happens when we want to wrap flat modules in an application but we have no process to start and thus no need for an application callback module?</p>
<p>After pulling our hair and crying in rage for a few minutes, the only other thing left to do is to remove the tuple <code>{mod, {Module, Args}}</code> from the application file. That's it. This is called a <em>library application</em>. If you want an example of one, the Erlang <code>stdlib</code> (standard library) application is one of these.</p>
<p>If you have the source package of Erlang, you can go to <code>otp_src_<release>/lib/stdlib/src/stdlib.app.src</code> and see the following:</p>
<pre class="brush:erl">
{application, stdlib,
[{description, "ERTS CXC 138 10"},
{vsn, "%VSN%"},
{modules, [array,
...
gen_event,
gen_fsm,
gen_server,
io,
...
lists,
...
zip]},
{registered,[timer_server,rsh_starter,take_over_monitor,pool_master,
dets]},
{applications, [kernel]},
{env, []}]}.
</pre>
<p>You can see it's a pretty standard application file, but without the callback module. A library application.</p>
<p>How about we go deeper with applications?</p>
<ul class="navigation">
<li><a href="building-applications-with-otp.html" title="Previous chapter">< Previous</a></li>
<li><a href="contents.html" title="Index">Index</a></li>
<li><a href="the-count-of-applications.html" title="Next chapter">Next ></a></li>
</ul>
</div><!-- content -->
<div id="footer">
<a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License Details"><img src="static/img/cc.png" width="88" height="31" alt="Creative Commons Attribution Non-Commercial No Derivative License" /></a>
<p>Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution Non-Commercial No Derivative License</p>
</div> <!-- footer -->
</div> <!-- wrapper -->
<div id="grass" />
<script type="text/javascript" src="static/js/shCore.js"></script>
<script type="text/javascript" src="static/js/shBrushErlang2.js%3F11"></script>
<script type="text/javascript">
SyntaxHighlighter.defaults.gutter = false;
SyntaxHighlighter.all();
</script>
</body>
</html>