aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CONTRIBUTING.md98
-rw-r--r--erts/doc/src/erl.xml19
-rw-r--r--erts/emulator/sys/unix/sys.c40
-rw-r--r--erts/emulator/test/emulator_smoke.spec12
-rwxr-xr-xscripts/run-smoke-tests10
-rw-r--r--system/doc/reference_manual/typespec.xml89
7 files changed, 223 insertions, 47 deletions
diff --git a/.travis.yml b/.travis.yml
index 43bf0c7fb5..ef17d6fbe7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,4 +40,4 @@ after_success:
- ./otp_build tests && make release_docs
after_script:
- - cd $ERL_TOP/release/tests/test_server && $ERL_TOP/bin/erl -s ts install -s ts smoke_test batch -s init stop
+ - ./scripts/run-smoke-tests
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..328b9f7859
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,98 @@
+# Contributing to Erlang/OTP
+
+## Reporting a bug
+
+Report bugs at https://bugs.erlang.org. See [Bug reports](https://github.com/erlang/otp/wiki/Bug-reports)
+for more information.
+
+## Submitting Pull Requests
+
+You can contribute to Erlang/OTP by opening a Pull Request.
+
+## Fixing a bug
+
+* In most cases, pull requests for bug fixes should be based on the `maint` branch.
+There are exceptions, for example corrections to bugs that have been introduced in the `master` branch.
+
+* Include a test case to ensure that the bug is fixed **and that it stays fixed**.
+
+* TIP: Write the test case **before** fixing the bug so that you can know that it catches the bug.
+
+* For applications without a test suite in the git repository, it would be appreciated if you provide a
+small code sample in the commit message or email a module that will provoke the failure.
+
+## Adding a new feature
+
+* In most cases, pull requests for new features should be based on the `master` branch.
+
+* It is recommended to discuss new features on
+[the erlang-questions mailing list](http://erlang.org/mailman/listinfo/erlang-questions),
+especially for major new features or any new features in ERTS, Kernel, or STDLIB.
+
+* It is important to write a good commit message explaining **why** the feature is needed.
+We prefer that the information is in the commit message, so that anyone that want to know
+two years later why a particular feature can easily find out. It does no harm to provide
+the same information in the pull request (if the pull request consists of a single commit,
+the commit message will be added to the pull request automatically).
+
+* With few exceptions, it is mandatory to write a new test case that tests the feature.
+The test case is needed to ensure that the features does not stop working in the future.
+
+* Update the [Documentation](https://github.com/erlang/otp/wiki/Documentation) to describe the feature.
+
+* Make sure that the new feature builds and works on all major platforms. Exceptions are features
+that only makes sense one some platforms, for example the `win32reg` module for accessing the Windows registry.
+
+* Make sure that your feature does not break backward compatibility. In general, we only break backward
+compatibility in major releases and only for a very good reason. Usually we first deprecate the
+feature one or two releases beforehand.
+
+* In general, language changes/extensions require an
+[EEP (Erlang Enhancement Proposal)](https://github.com/erlang/eep) to be written and approved before they
+can be included in OTP. Major changes or new features in ERTS, Kernel, or STDLIB will need an EEP or at least
+a discussion on the mailing list.
+
+## Before you submit your pull request
+
+* Make sure existing test cases don't fail. It is not necessary to run all tests (that would take many hours),
+but you should at least run the tests for the application you have changed.
+See [Running tests](https://github.com/erlang/otp/wiki/Running-tests).
+
+Make sure that your branch contains clean commits:
+
+* Don't make the first line in the commit message longer than 72 characters.
+**Don't end the first line with a period.**
+
+* Follow the guidelines for [Writing good commit messages](https://github.com/erlang/otp/wiki/Writing-good-commit-messages).
+
+* Don't merge `maint` or `master` into your branch. Use `git rebase` if you need to resolve merge
+conflicts or include the latest changes.
+
+* To make it possible to use the powerful `git bisect` command, make sure that each commit can be
+compiled and that it works.
+
+* Check for unnecessary whitespace before committing with `git diff --check`.
+
+Check your coding style:
+
+* Make sure your changes follow the coding and indentation style of the code surrounding your changes.
+
+* Do not commit commented-out code or files that are no longer needed. Remove the code or the files.
+
+* In most code (Erlang and C), indentation is 4 steps. Indentation using only spaces is **strongly recommended**.
+
+### Configuring Emacs
+
+If you use Emacs, use the Erlang mode, and add the following lines to `.emacs`:
+
+ (setq-default indent-tabs-mode nil)
+ (setq c-basic-offset 4)
+
+If you want to change the setting only for the Erlang mode, you can use a hook like this:
+
+```
+(add-hook 'erlang-mode-hook 'my-erlang-hook)
+
+(defun my-erlang-hook ()
+ (setq indent-tabs-mode nil))
+```
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index f2a55f6298..8da832ac37 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -1595,6 +1595,25 @@
</section>
<section>
+ <marker id="signals"></marker>
+ <title>Signals</title>
+ <p>On Unix systems, the Erlang runtime will interpret two types of signals.</p>
+ <taglist>
+ <tag><c>SIGUSR1</c></tag>
+ <item>
+ <p>A <c>SIGUSR1</c> signal forces a crash dump.</p>
+ </item>
+ <tag><c>SIGTERM</c></tag>
+ <item>
+ <p>A <c>SIGTERM</c> will produce a <c>stop</c> message to the <c>init</c> process.
+ This is equivalent to a <c>init:stop/0</c> call.</p>
+ <p>Introduced in ERTS 8.3 (Erlang/OTP 19.3)</p>
+ </item>
+ </taglist>
+ <p>The signal <c>SIGUSR2</c> is reserved for internal usage. No other signals are handled.</p>
+ </section>
+
+ <section>
<marker id="configuration"></marker>
<title>Configuration</title>
<p>The standard Erlang/OTP system can be reconfigured to change the default
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 4b2edace0a..2fc802a2c6 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -407,6 +407,7 @@ erts_sys_pre_init(void)
#ifdef ERTS_THR_HAVE_SIG_FUNCS
sigemptyset(&thr_create_sigmask);
sigaddset(&thr_create_sigmask, SIGINT); /* block interrupt */
+ sigaddset(&thr_create_sigmask, SIGTERM); /* block terminate signal */
sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
#endif
@@ -655,6 +656,40 @@ static RETSIGTYPE request_break(int signum)
#endif
}
+static void stop_requested(void) {
+ Process* p = NULL;
+ Eterm msg, *hp;
+ ErtsProcLocks locks = 0;
+ ErlOffHeap *ohp;
+ Eterm id = erts_whereis_name_to_id(NULL, am_init);
+
+ if ((p = (erts_pid2proc_opt(NULL, 0, id, 0, ERTS_P2P_FLG_INC_REFC))) != NULL) {
+ ErtsMessage *msgp = erts_alloc_message_heap(p, &locks, 3, &hp, &ohp);
+
+ /* init ! {stop,stop} */
+ msg = TUPLE2(hp, am_stop, am_stop);
+ erts_queue_message(p, locks, msgp, msg, am_system);
+
+ if (locks)
+ erts_smp_proc_unlock(p, locks);
+ erts_proc_dec_refc(p);
+ }
+}
+
+#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
+static RETSIGTYPE request_stop(void)
+#else
+static RETSIGTYPE request_stop(int signum)
+#endif
+{
+#ifdef ERTS_SMP
+ smp_sig_notify('S');
+#else
+ stop_requested();
+#endif
+}
+
+
static ERTS_INLINE void
sigusr1_exit(void)
{
@@ -751,6 +786,7 @@ static RETSIGTYPE do_quit(int signum)
/* Disable break */
void erts_set_ignore_break(void) {
sys_signal(SIGINT, SIG_IGN);
+ sys_signal(SIGTERM, SIG_IGN);
sys_signal(SIGQUIT, SIG_IGN);
sys_signal(SIGTSTP, SIG_IGN);
}
@@ -776,6 +812,7 @@ void erts_replace_intr(void) {
void init_break_handler(void)
{
sys_signal(SIGINT, request_break);
+ sys_signal(SIGTERM, request_stop);
#ifndef ETHR_UNUSABLE_SIGUSRX
sys_signal(SIGUSR1, user_signal1);
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
@@ -1289,6 +1326,9 @@ signal_dispatcher_thread_func(void *unused)
switch (buf[i]) {
case 0: /* Emulator initialized */
break;
+ case 'S': /* SIGTERM */
+ stop_requested();
+ break;
case 'I': /* SIGINT */
break_requested();
break;
diff --git a/erts/emulator/test/emulator_smoke.spec b/erts/emulator/test/emulator_smoke.spec
index 3219aeb823..b2d0de8835 100644
--- a/erts/emulator/test/emulator_smoke.spec
+++ b/erts/emulator/test/emulator_smoke.spec
@@ -1,3 +1,9 @@
-{suites,"../emulator_test",[smoke_test_SUITE,time_SUITE]}.
-{cases,"../emulator_test",crypto_SUITE,[t_md5]}.
-{cases,"../emulator_test",float_SUITE,[fpe,cmp_integer]}. \ No newline at end of file
+{define,'Dir',"../emulator_test"}.
+{suites,'Dir',[smoke_test_SUITE]}.
+{suites,'Dir',[time_SUITE]}.
+{skip_cases,'Dir',time_SUITE,
+ [univ_to_local,local_to_univ],"Depends on CET timezone"}.
+{skip_cases,'Dir',time_SUITE,
+ [consistency],"Not reliable in October and March"}.
+{cases,'Dir',crypto_SUITE,[t_md5]}.
+{cases,'Dir',float_SUITE,[fpe,cmp_integer]}.
diff --git a/scripts/run-smoke-tests b/scripts/run-smoke-tests
new file mode 100755
index 0000000000..c2333e7825
--- /dev/null
+++ b/scripts/run-smoke-tests
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -ev
+
+cd $ERL_TOP/release/tests/test_server
+$ERL_TOP/bin/erl -s ts install -s ts smoke_test batch -s init stop
+
+if grep -q '=failed *[1-9]' ct_run.test_server@*/*/run.*/suite.log; then
+ echo "One or more tests failed."
+ exit 1
+fi
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index ced584ed35..a0ea41cb3b 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -11,7 +11,7 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -63,7 +63,7 @@
Types consist of, and are built from, a set of predefined types,
for example, <c>integer()</c>, <c>atom()</c>, and <c>pid()</c>.
Predefined types represent a typically infinite set of Erlang terms that
- belong to this type. For example, the type <c>atom()</c> stands for the
+ belong to this type. For example, the type <c>atom()</c> denotes the
set of all Erlang atoms.
</p>
<p>
@@ -131,19 +131,19 @@
| nonempty_improper_list(Type1, Type2) %% Type1 and Type2 as above
| nonempty_list(Type) %% Proper non-empty list
- Map :: map() %% stands for a map of any size
- | #{} %% stands for the empty map
+ Map :: map() %% denotes a map of any size
+ | #{} %% denotes the empty map
| #{PairList}
- Tuple :: tuple() %% stands for a tuple of any size
+ Tuple :: tuple() %% denotes a tuple of any size
| {}
| {TList}
PairList :: Pair
| Pair, PairList
- Pair :: Type := Type %% denotes a pair that must be present
- | Type => Type
+ Pair :: Type := Type %% denotes a mandatory pair
+ | Type => Type %% denotes an optional pair
TList :: Type
| Type, TList
@@ -161,7 +161,7 @@
that <c>M</c> or <c>N</c>, or both, are zero.
</p>
<p>
- Because lists are commonly used, they have shorthand type notations.
+ Because lists are commonly used, they have shorthand type notations.
The types <c>list(T)</c> and <c>nonempty_list(T)</c> have the shorthands
<c>[T]</c> and <c>[T,...]</c>, respectively.
The only difference between the two shorthands is that <c>[T]</c> can be an
@@ -169,14 +169,18 @@
</p>
<p>
Notice that the shorthand for <c>list()</c>, that is, the list of
- elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
+ elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
The notation <c>[]</c> specifies the singleton type for the empty list.
</p>
<p>
The general form of maps is <c>#{PairList}</c>. The key types in
<c>PairList</c> are allowed to overlap, and if they do, the
leftmost pair takes precedence. A map pair has a key in
- <c>PairList</c> if it belongs to this type.
+ <c>PairList</c> if it belongs to this type. A <c>PairList</c> may contain
+ both 'mandatory' and 'optional' pairs where 'mandatory' denotes that
+ a key type, and its associated value type, must be present.
+ In the case of an 'optional' pair it is not required for the key type to
+ be present.
</p>
<p>
Notice that the syntactic representation of <c>map()</c> is
@@ -184,8 +188,8 @@
The notation <c>#{}</c> specifies the singleton type for the empty map.
</p>
<p>
- For convenience, the following types are also built-in.
- They can be thought as predefined aliases for the type unions also shown in
+ For convenience, the following types are also built-in.
+ They can be thought as predefined aliases for the type unions also shown in
the table.
</p>
<table>
@@ -201,37 +205,37 @@
<row>
<cell><c>bitstring()</c></cell><cell><c>&lt;&lt;_:_*1&gt;&gt;</c></cell>
</row>
- <row>
+ <row>
<cell><c>boolean()</c></cell><cell><c>'false' | 'true'</c></cell>
</row>
- <row>
+ <row>
<cell><c>byte()</c></cell><cell><c>0..255</c></cell>
</row>
<row>
<cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell>
</row>
- <row>
+ <row>
<cell><c>nil()</c></cell><cell><c>[]</c></cell>
</row>
<row>
<cell><c>number()</c></cell><cell><c>integer() | float()</c></cell>
</row>
- <row>
+ <row>
<cell><c>list()</c></cell><cell><c>[any()]</c></cell>
</row>
- <row>
+ <row>
<cell><c>maybe_improper_list()</c></cell><cell><c>maybe_improper_list(any(), any())</c></cell>
</row>
- <row>
+ <row>
<cell><c>nonempty_list()</c></cell><cell><c>nonempty_list(any())</c></cell>
</row>
<row>
<cell><c>string()</c></cell><cell><c>[char()]</c></cell>
</row>
- <row>
+ <row>
<cell><c>nonempty_string()</c></cell><cell><c>[char(),...]</c></cell>
</row>
- <row>
+ <row>
<cell><c>iodata()</c></cell><cell><c>iolist() | binary()</c></cell>
</row>
<row>
@@ -243,7 +247,7 @@
<row>
<cell><c>module()</c></cell><cell><c>atom()</c></cell>
</row>
- <row>
+ <row>
<cell><c>mfa()</c></cell><cell><c>{module(),atom(),arity()}</c></cell>
</row>
<row>
@@ -259,7 +263,7 @@
<cell><c>timeout()</c></cell><cell><c>'infinity' | non_neg_integer()</c></cell>
</row>
<row>
- <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
+ <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
</row>
<tcaption>Built-in types, predefined aliases</tcaption>
</table>
@@ -284,11 +288,11 @@
</row>
<tcaption>Additional built-in types</tcaption>
</table>
-
+
<p>
Users are not allowed to define types with the same names as the
predefined or built-in ones. This is checked by the compiler and
- its violation results in a compilation error.
+ its violation results in a compilation error.
</p>
<note>
<p>
@@ -394,13 +398,13 @@
<pre>
-record(rec, {field1 :: Type1, field2, field3 :: Type3}).</pre>
<p>
- For fields without type annotations, their type defaults to any().
+ For fields without type annotations, their type defaults to any().
That is, the previous example is a shorthand for the following:
</p>
<pre>
-record(rec, {field1 :: Type1, field2 :: any(), field3 :: Type3}).</pre>
<p>
- In the presence of initial values for fields,
+ In the presence of initial values for fields,
the type must be declared after the initialization, as follows:
</p>
<pre>
@@ -409,12 +413,12 @@
The initial values for fields are to be compatible
with (that is, a member of) the corresponding types.
This is checked by the compiler and results in a compilation error
- if a violation is detected.
+ if a violation is detected.
</p>
<note>
<p>Before Erlang/OTP 19, for fields without initial values,
the singleton type <c>'undefined'</c> was added to all declared types.
- In other words, the following two record declarations had identical
+ In other words, the following two record declarations had identical
effects:</p>
<pre>
-record(rec, {f1 = 42 :: integer(),
@@ -430,22 +434,22 @@
</p>
</note>
<p>
- Any record, containing type information or not, once defined,
+ Any record, containing type information or not, once defined,
can be used as a type using the following syntax:
</p>
<pre> #rec{}</pre>
<p>
- In addition, the record fields can be further specified when using
+ In addition, the record fields can be further specified when using
a record type by adding type information about the field
as follows:
</p>
<pre> #rec{some_field :: Type}</pre>
<p>
- Any unspecified fields are assumed to have the type in the original
+ Any unspecified fields are assumed to have the type in the original
record declaration.
</p>
</section>
-
+
<section>
<title>Specifications for Functions</title>
<p>
@@ -459,9 +463,9 @@
else a compilation error occurs.
</p>
<p>
- This form can also be used in header files (.hrl) to declare type
- information for exported functions.
- Then these header files can be included in files that (implicitly or
+ This form can also be used in header files (.hrl) to declare type
+ information for exported functions.
+ Then these header files can be included in files that (implicitly or
explicitly) import these functions.
</p>
<p>
@@ -475,14 +479,14 @@
<pre>
-spec Function(ArgName1 :: Type1, ..., ArgNameN :: TypeN) -> RT.</pre>
<p>
- A function specification can be overloaded.
+ A function specification can be overloaded.
That is, it can have several types, separated by a semicolon (<c>;</c>):
</p>
<pre>
-spec foo(T1, T2) -> T3
; (T4, T5) -> T6.</pre>
<p>
- A current restriction, which currently results in a warning
+ A current restriction, which currently results in a warning
(not an error) by the compiler, is that the domains of
the argument types cannot overlap.
For example, the following specification results in a warning:
@@ -491,9 +495,9 @@
-spec foo(pos_integer()) -> pos_integer()
; (integer()) -> integer().</pre>
<p>
- Type variables can be used in specifications to specify relations for
- the input and output arguments of a function.
- For example, the following specification defines the type of a
+ Type variables can be used in specifications to specify relations for
+ the input and output arguments of a function.
+ For example, the following specification defines the type of a
polymorphic identity function:
</p>
<pre>
@@ -542,8 +546,8 @@
-spec foo({X, integer()}) -> X when X :: atom()
; ([Y]) -> Y when Y :: number().</pre>
<p>
- Some functions in Erlang are not meant to return;
- either because they define servers or because they are used to
+ Some functions in Erlang are not meant to return;
+ either because they define servers or because they are used to
throw exceptions, as in the following function:
</p>
<pre> my_error(Err) -> erlang:throw({error, Err}).</pre>
@@ -555,4 +559,3 @@
<pre> -spec my_error(term()) -> no_return().</pre>
</section>
</chapter>
-