aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HOWTO/INSTALL-RASPBERRYPI3.md323
-rw-r--r--Makefile.in2
-rw-r--r--README.md2
-rw-r--r--erts/doc/src/erl_nif.xml42
-rw-r--r--erts/doc/src/net.xml3
-rw-r--r--erts/doc/src/notes.xml176
-rw-r--r--erts/doc/src/socket.xml5
-rw-r--r--erts/emulator/beam/beam_load.c2
-rw-r--r--erts/emulator/beam/erl_nif.c41
-rw-r--r--erts/emulator/beam/erl_nif.h23
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h3
-rw-r--r--erts/emulator/nifs/common/net_nif.c181
-rw-r--r--erts/emulator/nifs/common/socket_int.h412
-rw-r--r--erts/emulator/nifs/common/socket_nif.c2459
-rw-r--r--erts/emulator/nifs/common/socket_util.c2
-rw-r--r--erts/emulator/test/nif_SUITE.erl43
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c33
-rw-r--r--erts/emulator/test/socket_SUITE.erl1
-rw-r--r--erts/emulator/test/socket_test_evaluator.erl2
-rw-r--r--erts/vsn.mk2
-rw-r--r--lib/common_test/doc/src/notes.xml60
-rw-r--r--lib/common_test/test_server/ts_erl_config.erl36
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/notes.xml32
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl32
-rw-r--r--lib/compiler/test/float_SUITE.erl23
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/crypto/doc/src/notes.xml32
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/notes.xml30
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/doc/src/notes.xml35
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/edoc/doc/src/notes.xml16
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml26
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/configure.in10
-rw-r--r--lib/erl_interface/doc/src/ei.xml2
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml10
-rw-r--r--lib/erl_interface/doc/src/notes.xml17
-rw-r--r--lib/erl_interface/include/ei.h17
-rw-r--r--lib/erl_interface/include/ei_config.h.in3
-rw-r--r--lib/erl_interface/src/Makefile.in5
-rw-r--r--lib/erl_interface/src/misc/eidef.h1
-rw-r--r--lib/erl_interface/test/all_SUITE_data/Makefile.src4
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_format_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_print_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_format_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_global_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/erl_match_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/port_call_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/ftp/doc/src/notes.xml18
-rw-r--r--lib/ftp/vsn.mk2
-rw-r--r--lib/hipe/doc/src/notes.xml15
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/inets/doc/src/notes.xml38
-rw-r--r--lib/inets/src/http_server/mod_esi.erl6
-rw-r--r--lib/inets/test/httpd_SUITE.erl15
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/kernel/doc/src/application.xml4
-rw-r--r--lib/kernel/doc/src/logger.xml4
-rw-r--r--lib/kernel/doc/src/notes.xml179
-rw-r--r--lib/kernel/src/kernel.appup.src6
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/notes.xml17
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml39
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/doc/src/notes.xml17
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/public_key/doc/src/notes.xml15
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/runtime_tools/doc/src/notes.xml15
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/ssh/doc/src/notes.xml17
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml87
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/notes.xml51
-rw-r--r--lib/stdlib/src/stdlib.appup.src6
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/notes.xml14
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tools/doc/src/notes.xml39
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/doc/src/notes.xml19
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--make/otp_version_tickets_in_merge79
-rw-r--r--otp_versions.table1
100 files changed, 2907 insertions, 2018 deletions
diff --git a/HOWTO/INSTALL-RASPBERRYPI3.md b/HOWTO/INSTALL-RASPBERRYPI3.md
index 536d095cb4..b9cffbe0c5 100644
--- a/HOWTO/INSTALL-RASPBERRYPI3.md
+++ b/HOWTO/INSTALL-RASPBERRYPI3.md
@@ -4,7 +4,7 @@
## Introduction
This document describes how to build a toolchain and cross compile Erlang/OTP
-to Raspberry Pi 3 on macOS High Sierra. It is recommended to consult
+to Raspberry Pi 3 on macOS Mojave. It is recommended to consult
[Building and Installing Erlang/OTP](https://github.com/erlang/otp/blob/master/HOWTO/INSTALL.md) and [Cross Compiling Erlang/OTP](https://github.com/erlang/otp/blob/master/HOWTO/INSTALL-CROSS.md) before attempting to follow the instructions in this guide.
The whole process takes several hours and depending on the package versions different problems may arise that require additional
@@ -18,9 +18,15 @@ toolchain and sysroot.
#### Tested Configuration
-macOS High Sierra 10.13.2<br>
+macOS Mojave 10.14.3<br>
Raspberry Pi Model B Rev 1.2<br>
-Crosstools-NG 1.23.0_1
+Crosstools-NG 1.23.0_3
+
+```
+build = x86_64-apple-darwin18.2.0
+host = x86_64-apple-darwin18.2.0
+target = armv8-rpi3-linux-gnueabihf
+```
> Note: /proc/device/tree/model contains model information of your
> Raspberry Pi.
@@ -34,10 +40,13 @@ Crosstools-NG 1.23.0_1
$ brew install grep --default-names # needed by crosstools-ng scripts
$ brew install md5sha1sum # needed by crosstools-ng populate script
+ (2)
+
+ $ chmod 744 /usr/local/Cellar/crosstool-ng/1.23.0_3/lib/crosstool-ng-1.23.0/scripts/crosstool-NG.sh
#### Create case-sensitive disk images
- (2)
+ (3)
Create two case-sensitive disk images using Disk Utility:
@@ -47,47 +56,106 @@ Format: `Mac OS Extended (Case-sensitive, Journaled)`
```
/Volumes/xtools-build-env 15 GB
-/Volumes/xtools           500 MB
+/Volumes/xtools 500 MB
```
-The first image holds all source and object files while building the toolchain. The second image houses the compiled
+> The first image holds all source and object files while building the toolchain. The second image houses the compiled
toolchain.
-## Building the Toolchain
+## Building the Toolchain
-#### Configure crosstool-ng
+### Environment settings
(4)
+ $ ulimit -n 1024
+
+### Inspect target system
+
+ (5)
+
+ $ uname -a
+ Linux raspberrypi 4.9.35-v7+ #1014 SMP Fri Jun 30 14:47:43 BST 2017 armv7l GNU/Linux
+ $ ld -v
+ GNU ld (GNU Binutils for Raspbian) 2.25
+ $ ldd --version
+ ldd (Debian GLIBC 2.19-18+deb8u10) 2.19
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ This is free software; see the source for copying conditions. There is NO
+ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ Written by Roland McGrath and Ulrich Drepper.
+
+> Use the versions available on your target system!
+
+> See https://wiki.osdev.org/Cross-Compiler_Successful_Builds
+
+### Configure crosstool-ng
+
+ (6)
+
+ $ cd /Volumes/xtools-build-env
$ ct-ng armv8-rpi3-linux-gnueabihf
$ ct-ng menuconfig
-#### Modify *path* section
+#### Path and misc options
+
+##### crosstool-NG behavior
+
+ (7)
+
+```
+[*] Use obsolete features
+
+[*] Debug crosstool-NG
+[ ] Pause between every steps
+[*] Save intermediate steps
+[*] gzip saved states
+[*] Interactive shell on failed commands
+```
+
+> Should the build break at a particular build step, you can fix the problem and continue the build from where it broke.
+
+##### Paths
+
+ (8)
* Local tarballs directory: `/Volumes/xtools-build-env/src`
* Working directory: `/Volumes/xtools-build-env/.build`
* Prefix directory: `/Volumes/xtools/${CT_TARGET}`
-#### Modify *Extracting* section
+##### Extracting
+
+ (9)
+
+`[*] Stop after extracting tarballs`
-* Check option: _Stop after extracting tarballs_.
+> Stop the build process right after the tarballs have been extracted. This can be handy to fix known source code problems before the actual build process is started.
-> Note: The build shall stop after the tarballs have been extracted to give us time to fix source code problems.
+#### Operating System
-#### Enable STOP / RESTART
+ (10)
-Edit /Volumes/xtools-build-env/.config
-  `CT_DEBUG_CT_SAVE_STEPS=y`
+`Linux kernel version (4.9.20)`
-Should the build break at a particular build step, you can fix the problem and continue the build from where it broke.
+#### Binary utilities
-Short summary of the most common `ct-ng` commands:
+ (11)
-* Listing all build steps
+`bintutils version (2.28)`
+
+#### C-library
+
+ (12)
+
+`glibc version (2.19 (OBSOLETE))`
+
+#### Sample `ct-ng` commands:
+
+* List all build steps
```
-    $ ct-ng list-steps
+ $ ct-ng list-steps
Available build steps, in order:
- companion_tools_for_build
@@ -108,216 +176,153 @@ Short summary of the most common `ct-ng` commands:
- binutils_for_target
- debug
- test_suite
-    - finish
+ - finish
```
-* Re-run step
-```
-    $ ct-ng step
-```
+* Re-run step `companion_libs_for_host`
-* Restart from step
```
-    $ ct-ng step+
+ $ ct-ng companion_libs_for_host
```
-* Run until step
+* Restart from `companion_libs_for_host`
+
```
-    $ ct-ng +step
+ $ ct-ng companion_libs_for_host+
```
-#### Fix file permissions on crosstool-NG.sh
-
- (5)
-
- $ chmod 744 /usr/local/Cellar/crosstool-ng/1.23.0_1/lib/crosstool-ng-1.23.0/scripts/crosstool-NG.sh
+* Run until step `companion_libs_for_host`
-#### Run build command
+```
+ $ ct-ng +companion_libs_for_host
+```
-Build process stops just after the tarballs have been extracted.
+### Build
- (6)
+ (13)
$ ct-ng build
- Retrieving needed toolchain components' tarballs
- [EXTRA] Retrieving 'make-4.2.1'
- [EXTRA] Retrieving 'm4-1.4.18'
- [EXTRA] Retrieving 'linux-4.10.8'
- [EXTRA] Retrieving 'gmp-6.1.2'
- [EXTRA] Retrieving 'mpfr-3.1.5'
- [EXTRA] Retrieving 'isl-0.16.1'
- [EXTRA] Retrieving 'mpc-1.0.3'
- [EXTRA] Retrieving 'expat-2.2.0'
- [EXTRA] Retrieving 'ncurses-6.0'
- [EXTRA] Retrieving 'libiconv-1.15'
- [EXTRA] Retrieving 'gettext-0.19.8.1'
- [EXTRA] Retrieving 'binutils-2.28'
- [EXTRA] Retrieving 'gcc-6.3.0'
- [EXTRA] Retrieving 'glibc-2.25'
- [EXTRA] Retrieving 'gdb-7.12.1'
+> Build process stops just after the tarballs have been extracted.
#### Fix source files
- (7)
-
-Add macro to /Volumes/xtools-build-env/.build/src/gdb-7.12.1/gdb/doublest.c:
-```C
-#define min(a,b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
-    _a < _b ? _a : _b; })
-```
-
-  (8) Update ulimit
+ (14)
- $ ulimit -n 1024
+ $ pushd .build/src/gettext-0.19.8.1/
+ $ autoreconf
+ $ popd
-#### Modify *extract* section
+#### Update configuration
- (8)
+ (15)
$ ct-ng menuconfig
- Uncheck option: _Stop after extracting tarballs_
+Uncheck option:
-#### Re-run build command
+`[ ] Stop after extracting tarballs`
-Restarts build process from where it previously stopped.
+#### Continue build
- (9)
+ (16)
$ ct-ng build
-#### Fix gettext
+> Restart build process from where it previously stopped.
-Build will fail at step `companion_tools_for_build` but it can be fixed by running autoreconf:
+ (17)
- (10)
+ $ export PATH=/Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin:$PATH
- $ cd .build/src/gettext-0.19.8.1/
- $ ./autoreconf
- $ ct-ng companion_tools_for_build+
+### Test
-#### Test the toolchain
-
- (11)
+ (18)
$ cat > test.c
$ int main() { printf("Hello, world!\n"); return 0; }
- $ /Volumes/xtools/arm-unknown-linux-gnueabi-gcc -o test test.c
-
- (12) OPTIONAL
-
- “Render the toolchain read-only” from crosstool-NG’s “Paths and misc options” configuration page.
+ <CTRL+D>
+ $ armv8-rpi3-linux-gnueabihf-gcc -o test test.c
## Cross compiling dependencies
- (13)
+ (19)
- $ export PATH=/Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin:$PATH
+ $ mkdir local # prefix directory
+ $ mkdir 3pps # OTP dependencies
+ $ cd 3pps
-#### Cross compiling zlib
+#### zlib
- (14)
+ (20)
$ wget http://zlib.net/zlib-1.2.11.tar.gz
$ tar xf zlib-1.2.11.tar.gz
- $ cd zlib-1.2.11
- $ CHOST=armv8-rpi3-linux-gnueabihf ./configure --prefix=/Users/<username>/git/raspberrypi/arm
+ $ pushd zlib-1.2.11
+ $ CHOST=armv8-rpi3-linux-gnueabihf ./configure --prefix=/Volumes/xtools-build-env/local
$ make
$ make install
+ $ popd
-#### Cross compiling openssl
+#### openssl
- (15)
+ (21)
- $ wget http://openssl.org/source/openssl-1.1.0g.tar.gz
- $ tar xf openssl-1.1.0g.tar.gz
- $ cd openssl-1.1.0g
- $ ./Configure linux-generic32 --prefix=/Users/<username>/git/raspberrypi/arm --openssldir=/Users/<username>/git/raspberrypi/arm/openssl --cross-compile-prefix=armv8-rpi3-linux-gnueabihf
+ $ wget http://openssl.org/source/openssl-1.1.1b.tar.gz
+ $ tar xf openssl-1.1.1b.tar.gz
+ $ pushd openssl-1.1.1b
+ $ ./Configure linux-generic32 --prefix=/Volumes/xtools-build-env/local \
+ --openssldir=/Volumes/xtools-build-env/local/openssl \
+ --cross-compile-prefix=armv8-rpi3-linux-gnueabihf-
$ make
$ make install
+ $ popd
-#### Cross compiling ncurses
-
- (16)
-
- $ wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
+> A compatible openssl library shall be available on the target system!
+#### ncurses
- (17)
-
-Apply patch:
-
-```patch
---- a/ncurses/base/MKlib_gen.sh
-+++ b/ncurses/base/MKlib_gen.sh
-@@ -474,11 +474,22 @@ sed -n -f $ED1 \
- -e 's/gen_$//' \
- -e 's/ / /g' >>$TMP
-
-+cat >$ED1 <<EOF
-+s/ / /g
-+s/^ //
-+s/ $//
-+s/P_NCURSES_BOOL/NCURSES_BOOL/g
-+EOF
-+
-+# A patch discussed here:
-+# https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02185.html
-+# introduces spurious #line markers. Work around that by ignoring the system's
-+# attempt to define "bool" and using our own symbol here.
-+sed -e 's/bool/P_NCURSES_BOOL/g' $TMP > $ED2
-+cat $ED2 >$TMP
-+
- $preprocessor $TMP 2>/dev/null \
--| sed \
-- -e 's/ / /g' \
-- -e 's/^ //' \
-- -e 's/_Bool/NCURSES_BOOL/g' \
-+| sed -f $ED1 \
- | $AWK -f $AW2 \
- | sed -f $ED3 \
- | sed \
-```
+ (22)
-  (18)
-
- $ ./configure --build=x86_64-apple-darwin17.3.0 --host=armv8-rpi3-linux-gnueabihf --without-ada --without-cxx --without-cxx-binding --without-manpages --without-progs --without-tests --prefix=/usr --libdir=/lib --with-build-cc="gcc -D_GNU_SOURCE" --with-shared
+ $ wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
+ $ tar xf ncurses-5.9.tar.gz
+ $ pushd ncurses-5.9
+ $ wget https://gist.githubusercontent.com/peterdmv/1068b2f9e1fec6e1330ad62ed87461ad/\
+ raw/065597b63654ed6a9f28d02fdfbca844413847ad/ncurses-5.9.patch
+ $ patch -p0 < ncurses-5.9.patch
+ $ ./configure --build=x86_64-apple-darwin18.2.0 --host=armv8-rpi3-linux-gnueabihf \
+ --without-ada --without-cxx --without-cxx-binding --without-manpages \
+ --without-progs --without-tests --prefix=/usr --libdir=/lib \
+ --with-build-cc="gcc -D_GNU_SOURCE" --with-shared
$ make
- $ make DESTDIR=/Users/<username>/git/raspberrypi/arm install
-
- (19)
-
-Compile ncurses test program:
-
- $ cd test
- $ armv8-rpi3-linux-gnueabihf-gcc -o nctest ncurses.c -I${RPI_SYSROOT}/usr/include -L${RPI_SYSROOT}/lib -lncursesw
+ $ make DESTDIR=/Volumes/xtools-build-env/local install
+ $ popd
## Populating sysroot
- (19)
-
- Edit /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-populate:
+ (23)
- sed="gsed"
+ $ chmod 755 /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin
+ $ chmod 755 /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-populate
+ $ gsed -i 's/"sed"/"gsed"/g' \
+ /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-populate
+ $ chmod 555 /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin
+ $ chmod 555 /Volumes/xtools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-populate
- (20)
+ (24)
- $ armv8-rpi3-linux-gnueabihf-populate -s /Users/<username>/git/raspberrypi/arm -d /Users/<username>/git/raspberrypi/sysroot
- $ export RPI_SYSROOT=/Users/<username>/git/raspberrypi/sysroot
+ $ armv8-rpi3-linux-gnueabihf-populate -s /Volumes/xtools-build-env/local \
+ -d /Volumes/xtools-build-env/sysroot
+ $ export RPI_SYSROOT=/Volumes/xtools-build-env/sysroot
## Cross compiling Erlang/OTP
- (21)
+ (25)
$ LC_CTYPE=C && LANG=C && ./otp_build autoconf
- $ ./otp_build configure --disable-dynamic-ssl-lib --xcomp-conf=./xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf
+ $ ./otp_build configure --xcomp-conf=./xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf
$ ./otp_build boot -a
- $ ./otp_build release -a /Users/<username>/git/raspberrypi/erlang
- $ tar czf erlang.tgz ./erlang
-
+ $ ./otp_build release -a /Volumes/xtools-build-env/otp_22.0
diff --git a/Makefile.in b/Makefile.in
index 494ab52b3a..49a0d9f8af 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -769,7 +769,7 @@ tertiary_bootstrap_copy:
true; \
done
# copy erl_interface includes
- $(V_at)for x in lib/erl_interface/include/*.h lib/erl_interface/include/$(TARGET)/*.h; do \
+ $(V_at)for x in lib/erl_interface/include/*.h; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/erl_interface/include/$$BN; \
test -f $$TF && \
diff --git a/README.md b/README.md
index 5e051388d1..4cf018901c 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
**OTP** is a set of Erlang libraries, which consists of the Erlang runtime system, a number of ready-to-use components mainly written in Erlang, and a set of design principles for Erlang programs. [Learn more about Erlang and OTP](http://erlang.org/doc/system_architecture_intro/sys_arch_intro.html).
+[Release notes](http://erlang.org/download/otp_versions_tree.html) for all OTP versions.
+
[Learn how to program in Erlang](http://learnyousomeerlang.com/content).
## Examples
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index cc7452bab5..cf1994887a 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -3369,6 +3369,48 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
</func>
<func>
+ <name since="OTP @OTP-15640@"><ret>ErlNifTermType</ret>
+ <nametext>enif_term_type(ErlNifEnv *env, ERL_NIF_TERM term)</nametext>
+ </name>
+ <fsummary>Determine the type of a term.</fsummary>
+ <desc>
+ <p>Determines the type of the given term. The term must be an ordinary
+ Erlang term and not one of the special terms returned by
+ <seealso marker="#enif_raise_exception">
+ <c>enif_raise_exception</c></seealso>,
+ <seealso marker="#enif_schedule_nif">
+ <c>enif_schedule_nif</c></seealso>, or similar.</p>
+ <p>The following types are defined at the moment:</p>
+ <taglist>
+ <tag><c>ERL_NIF_TERM_TYPE_ATOM</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_BITSTRING</c></tag>
+ <item><p>A bitstring or binary</p></item>
+ <tag><c>ERL_NIF_TERM_TYPE_FLOAT</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_FUN</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_INTEGER</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_LIST</c></tag>
+ <item><p>A list, empty or not</p></item>
+ <tag><c>ERL_NIF_TERM_TYPE_MAP</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_PID</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_PORT</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_REFERENCE</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_TUPLE</c></tag>
+ <item/>
+ </taglist>
+ <p>Note that new types may be added in the future, so the caller must
+ be prepared to handle unknown types.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>int</ret>
<nametext>enif_thread_create(char *name,ErlNifTid
*tid,void * (*func)(void *),void *args,ErlNifThreadOpts
diff --git a/erts/doc/src/net.xml b/erts/doc/src/net.xml
index bd85594c98..b9e2cffce9 100644
--- a/erts/doc/src/net.xml
+++ b/erts/doc/src/net.xml
@@ -33,6 +33,9 @@
<modulesummary>Network interface.</modulesummary>
<description>
<p>This module provides an API for the network interface.</p>
+ <note>
+ <p>There is currently <em>no</em> support for Windows. </p>
+ </note>
</description>
<datatypes>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 2e1650516e..bdae994d06 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -31,6 +31,182 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 10.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>When multiplying a number by itself, a word beyond the
+ number on the heap could be read (and ignored). This bug
+ was extremely unlikely to actually cause a real
+ problem.</p>
+ <p>
+ Own Id: OTP-15484</p>
+ </item>
+ <item>
+ <p>
+ Fix bug where doing <c>seq_trace:reset_trace()</c> while
+ another process was doing a garbage collection could
+ cause the run-time system to segfault.</p>
+ <p>
+ Own Id: OTP-15490</p>
+ </item>
+ <item>
+ <p>
+ Fix reading of ancillary data from packet oriented
+ sockets on old Linux kernel versions. Without this fix,
+ getting the data would cause the port to enter an
+ infinite loop.</p>
+ <p>
+ Own Id: OTP-15494</p>
+ </item>
+ <item>
+ <p>
+ Fix bug where crash dumping or doing
+ <c>erlang:system_info(procs)</c> while another process
+ was doing a garbage collection could cause the run-time
+ system to segfault.</p>
+ <p>
+ Own Id: OTP-15527</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>erlang:system_info(kernel_poll)</c> to return
+ correct value. Before this fix, the call always returned
+ <c>false</c>.</p>
+ <p>
+ Own Id: OTP-15556</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>enif_make_map_from_arrays</c> that would
+ produce broken maps when number of keys were 32. Bug
+ exists since OTP 21.0.</p>
+ <p>
+ Own Id: OTP-15567</p>
+ </item>
+ <item>
+ <p>
+ Fix a bug in <c>binary:encode_unsigned</c> that may cause
+ a read of uninitialized memory.</p>
+ <p>
+ The bug existed since the function was added (OTP
+ R16B02).</p>
+ <p>
+ Own Id: OTP-15583 Aux Id: PR-2118 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug that could cause <c>heart</c> to kill an
+ exiting node before it had time to flush all buffered
+ writes. If environment variable
+ <c>HEART_KILL_SIGNAL=SIGABRT</c> was set a superfluous
+ core dump could also be generated.</p>
+ <p>
+ Own Id: OTP-15599 Aux Id: ERIERL-298 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>enif_consume_timeslice</c> to be a no-op on dirty
+ scheduler and not crash debug compiled emulator.</p>
+ <p>
+ Own Id: OTP-15604</p>
+ </item>
+ <item>
+ <p>
+ Fixed macro redefinition warnings.</p>
+ <p>
+ Own Id: OTP-15629</p>
+ </item>
+ <item>
+ <p>
+ <c>to_erl</c> fixed to not garble terminal input beyond
+ 7-bit ASCII.</p>
+ <p>
+ Own Id: OTP-15650 Aux Id: ERL-854, PR-2161 </p>
+ </item>
+ <item>
+ <p>
+ Minor fixes for <c>make clean</c>.</p>
+ <p>
+ Own Id: OTP-15657</p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug in all <c>ets:select*</c> and
+ <c>ets:match*</c> functions that could in some rare cases
+ lead to very poor performance.</p>
+ <p>
+ Own Id: OTP-15660 Aux Id: ERL-869 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add <c>erlang:system_flag(system_logger, Pid)</c> and
+ <c>erlang:system_info(system_logger)</c>. This
+ system_flag can be used to set the process that will
+ receive the logging messages generated by ERTS.</p>
+ <p>
+ Own Id: OTP-15375</p>
+ </item>
+ <item>
+ <p><c>integer_to_list/2</c> and
+ <c>integer_to_binary/2</c> are now implemented in C,
+ improving their performance.</p>
+ <p>
+ Own Id: OTP-15503 Aux Id: PR-2052 </p>
+ </item>
+ <item>
+ <p>
+ Improved <c>term_to_binary</c> to do more fair reduction
+ count and yielding when encoding large byte lists
+ (strings).</p>
+ <p>
+ Own Id: OTP-15514 Aux Id: ERL-774 </p>
+ </item>
+ <item>
+ <p>
+ Made internal port drivers more robust against
+ <c>erlang:port_control</c> with invalid arguments and
+ added documentation warnings about such abuse.</p>
+ <p>
+ Own Id: OTP-15555 Aux Id: ERIERL-231 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug on NetBSD where the <c>exit_status</c> from a
+ port program would never be sent.</p>
+ <p>
+ Own Id: OTP-15558 Aux Id: ERL-725 </p>
+ </item>
+ <item>
+ <p>There is a new function <c>persistent:term(Key,
+ Default)</c> to allow specifying a default when looking
+ up a persistent term.</p>
+ <p>
+ Own Id: OTP-15576 Aux Id: ERL-843 </p>
+ </item>
+ <item>
+ <p>A transitory emulator option '<c>+ztma true</c>' has
+ been added to allow running existing BEAM code that
+ relies on "tuple calls" (dispatch on parameterized
+ modules) which has been compiled under OTP 20 or earlier.
+ This option will be removed in OTP 22, so such modules
+ should eventually be recompiled with the
+ <c>+tuple_calls</c> option.</p>
+ <p>
+ Own Id: OTP-15580 Aux Id: PR-2113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 10.2.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml
index caf7058b34..f6195a65b2 100644
--- a/erts/doc/src/socket.xml
+++ b/erts/doc/src/socket.xml
@@ -40,6 +40,11 @@
the functions,
e.g. <seealso marker="#recv/3"><c>recv/3</c></seealso>,
has a timeout argument. </p>
+ <note>
+ <p>There is currently <em>no</em> support for Windows. </p>
+ <p>Support for IPv6 has been implemented but <em>not</em> tested. </p>
+ <p>SCTP has only been partly implemented (and not tested). </p>
+ </note>
</description>
<datatypes>
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 43adf7a5e0..0ad5329b2f 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1425,7 +1425,7 @@ load_atom_table(LoaderState* stp, ErtsAtomEncoding enc)
ap = atom_tab(atom_val(stp->atom[1]));
sys_memcpy(sbuf, ap->name, ap->len);
sbuf[ap->len] = '\0';
- LoadError1(stp, "module name in object code is %s", sbuf);
+ LoadError1(stp, "BEAM file exists but it defines a module named %s", sbuf);
}
return 1;
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 5a3cdf980d..af1acbfc90 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1175,6 +1175,47 @@ int enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)
return is_number(term);
}
+ErlNifTermType enif_term_type(ErlNifEnv* env, ERL_NIF_TERM term) {
+ (void)env;
+
+ switch (tag_val_def(term)) {
+ case ATOM_DEF:
+ return ERL_NIF_TERM_TYPE_ATOM;
+ case BINARY_DEF:
+ return ERL_NIF_TERM_TYPE_BITSTRING;
+ case FLOAT_DEF:
+ return ERL_NIF_TERM_TYPE_FLOAT;
+ case EXPORT_DEF:
+ case FUN_DEF:
+ return ERL_NIF_TERM_TYPE_FUN;
+ case BIG_DEF:
+ case SMALL_DEF:
+ return ERL_NIF_TERM_TYPE_INTEGER;
+ case LIST_DEF:
+ case NIL_DEF:
+ return ERL_NIF_TERM_TYPE_LIST;
+ case MAP_DEF:
+ return ERL_NIF_TERM_TYPE_MAP;
+ case EXTERNAL_PID_DEF:
+ case PID_DEF:
+ return ERL_NIF_TERM_TYPE_PID;
+ case EXTERNAL_PORT_DEF:
+ case PORT_DEF:
+ return ERL_NIF_TERM_TYPE_PORT;
+ case EXTERNAL_REF_DEF:
+ case REF_DEF:
+ return ERL_NIF_TERM_TYPE_REFERENCE;
+ case TUPLE_DEF:
+ return ERL_NIF_TERM_TYPE_TUPLE;
+ default:
+ /* tag_val_def() aborts on its own when passed complete garbage, but
+ * it's possible that the user has given us garbage that just happens
+ * to match something that tag_val_def() accepts but we don't, like
+ * binary match contexts. */
+ ERTS_INTERNAL_ERROR("Invalid term passed to enif_term_type");
+ }
+}
+
static void aligned_binary_dtor(struct enif_tmp_obj_t* obj)
{
erts_free_aligned_binary_bytes_extra((byte*)obj, obj->allocator);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 3fd1a8fd4c..a599511c78 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -55,6 +55,7 @@
** 2.14: 21.0 add enif_ioq_peek_head, enif_(mutex|cond|rwlock|thread)_name
** enif_vfprintf, enif_vsnprintf, enif_make_map_from_arrays
** 2.15: 22.0 ERL_NIF_SELECT_CANCEL, enif_select_(read|write)
+** enif_term_type
*/
#define ERL_NIF_MAJOR_VERSION 2
#define ERL_NIF_MINOR_VERSION 15
@@ -63,7 +64,7 @@
* with ticket syntax like "erts-@OTP-12345@", or a temporary placeholder
* between two @ like "erts-@MyName@", if you don't know what a ticket is.
*/
-#define ERL_NIF_MIN_ERTS_VERSION "erts-@OTP-15095@ (OTP-22)"
+#define ERL_NIF_MIN_ERTS_VERSION "erts-@OTP-15095 OTP-15640@ (OTP-22)"
/*
* The emulator will refuse to load a nif-lib with a major version
@@ -282,6 +283,26 @@ typedef enum {
ERL_NIF_IOQ_NORMAL = 1
} ErlNifIOQueueOpts;
+typedef enum {
+ ERL_NIF_TERM_TYPE_ATOM = 1,
+ ERL_NIF_TERM_TYPE_BITSTRING = 2,
+ ERL_NIF_TERM_TYPE_FLOAT = 3,
+ ERL_NIF_TERM_TYPE_FUN = 4,
+ ERL_NIF_TERM_TYPE_INTEGER = 5,
+ ERL_NIF_TERM_TYPE_LIST = 6,
+ ERL_NIF_TERM_TYPE_MAP = 7,
+ ERL_NIF_TERM_TYPE_PID = 8,
+ ERL_NIF_TERM_TYPE_PORT = 9,
+ ERL_NIF_TERM_TYPE_REFERENCE = 10,
+ ERL_NIF_TERM_TYPE_TUPLE = 11,
+
+ /* This is a dummy value intended to coax the compiler into warning about
+ * unhandled values in a switch even if all the above values have been
+ * handled. We can add new entries at any time so the user must always
+ * have a default case. */
+ ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1
+} ErlNifTermType;
+
/*
* Return values from enif_thread_type(). Negative values
* reserved for specific types of non-scheduler threads.
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 8ab454c8dd..d57f6ec97c 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -215,6 +215,8 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_monitor_term,(ErlNifEnv* env, const
ERL_NIF_API_FUNC_DECL(void,enif_set_pid_undefined,(ErlNifPid* pid));
ERL_NIF_API_FUNC_DECL(int,enif_is_pid_undefined,(const ErlNifPid* pid));
+ERL_NIF_API_FUNC_DECL(ErlNifTermType,enif_term_type,(ErlNifEnv* env, ERL_NIF_TERM term));
+
/*
** ADD NEW ENTRIES HERE (before this comment) !!!
*/
@@ -401,6 +403,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_pid_undefined,(const ErlNifPid* pid));
# define enif_make_monitor_term ERL_NIF_API_FUNC_MACRO(enif_make_monitor_term)
# define enif_set_pid_undefined ERL_NIF_API_FUNC_MACRO(enif_set_pid_undefined)
# define enif_is_pid_undefined ERL_NIF_API_FUNC_MACRO(enif_is_pid_undefined)
+# define enif_term_type ERL_NIF_API_FUNC_MACRO(enif_term_type)
/*
** ADD NEW ENTRIES HERE (before this comment)
diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c
index 9a18ed3b15..6c91bd74bd 100644
--- a/erts/emulator/nifs/common/net_nif.c
+++ b/erts/emulator/nifs/common/net_nif.c
@@ -240,35 +240,37 @@ static NetData data;
/* THIS IS JUST TEMPORARY */
extern char* erl_errno_id(int error);
+/* All the nif "callback" functions for the net API has
+ * the exact same API:
+ *
+ * nif_<funcname>(ErlNifEnv* env,
+ * int argc,
+ * const ERL_NIF_TERM argv[]);
+ *
+ * So, to simplify, use some macro magic to define those.
+ *
+ * These are the functions making up the "official" API.
+ */
-static ERL_NIF_TERM nif_info(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_command(ErlNifEnv* env,
- int argc,
+#define ENET_NIF_FUNCS \
+ ENET_NIF_FUNC_DEF(info); \
+ ENET_NIF_FUNC_DEF(command); \
+ ENET_NIF_FUNC_DEF(gethostname); \
+ ENET_NIF_FUNC_DEF(getnameinfo); \
+ ENET_NIF_FUNC_DEF(getaddrinfo); \
+ ENET_NIF_FUNC_DEF(if_name2index); \
+ ENET_NIF_FUNC_DEF(if_index2name); \
+ ENET_NIF_FUNC_DEF(if_names);
+
+#define ENET_NIF_FUNC_DEF(F) \
+ static ERL_NIF_TERM nif_##F(ErlNifEnv* env, \
+ int argc, \
const ERL_NIF_TERM argv[]);
+ENET_NIF_FUNCS
+#undef ENET_NIF_FUNC_DEF
-static ERL_NIF_TERM nif_gethostname(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-
-static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-
-static ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_if_names(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
+/* And here comes the functions that does the actual work (for the most part) */
static ERL_NIF_TERM ncommand(ErlNifEnv* env,
ERL_NIF_TERM cmd);
static ERL_NIF_TERM ngethostname(ErlNifEnv* env);
@@ -359,66 +361,42 @@ static const struct in6_addr in6addr_loopback =
-/* *** String constants *** */
-static char str_address_info[] = "address_info";
-static char str_debug[] = "debug";
-static char str_idn[] = "idn";
-static char str_idna_allow_unassigned[] = "idna_allow_unassigned";
-static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules";
-static char str_namereqd[] = "namereqd";
-static char str_name_info[] = "name_info";
-static char str_nofqdn[] = "nofqdn";
-static char str_numerichost[] = "numerichost";
-static char str_numericserv[] = "numericserv";
-
-/* (special) error string constants */
-static char str_eaddrfamily[] = "eaddrfamily";
-static char str_ebadflags[] = "ebadflags";
-static char str_efail[] = "efail";
-static char str_efamily[] = "efamily";
-static char str_efault[] = "efault";
-static char str_emem[] = "emem";
-static char str_enametoolong[] = "enametoolong";
-static char str_enodata[] = "enodata";
-static char str_enoname[] = "enoname";
-static char str_enxio[] = "enxio";
-static char str_eoverflow[] = "eoverflow";
-static char str_eservice[] = "eservice";
-static char str_esocktype[] = "esocktype";
-static char str_esystem[] = "esystem";
-
-
-/* *** Atoms *** */
-
-static ERL_NIF_TERM atom_address_info;
-static ERL_NIF_TERM atom_debug;
-static ERL_NIF_TERM atom_host;
-static ERL_NIF_TERM atom_idn;
-static ERL_NIF_TERM atom_idna_allow_unassigned;
-static ERL_NIF_TERM atom_idna_use_std3_ascii_rules;
-static ERL_NIF_TERM atom_namereqd;
-static ERL_NIF_TERM atom_name_info;
-static ERL_NIF_TERM atom_nofqdn;
-static ERL_NIF_TERM atom_numerichost;
-static ERL_NIF_TERM atom_numericserv;
-static ERL_NIF_TERM atom_service;
-
-
-static ERL_NIF_TERM atom_eaddrfamily;
-// static ERL_NIF_TERM atom_eagain;
-static ERL_NIF_TERM atom_ebadflags;
-static ERL_NIF_TERM atom_efail;
-static ERL_NIF_TERM atom_efamily;
-static ERL_NIF_TERM atom_efault;
-static ERL_NIF_TERM atom_emem;
-static ERL_NIF_TERM atom_enametoolong;
-static ERL_NIF_TERM atom_enodata;
-static ERL_NIF_TERM atom_enoname;
-static ERL_NIF_TERM atom_enxio;
-static ERL_NIF_TERM atom_eoverflow;
-static ERL_NIF_TERM atom_eservice;
-static ERL_NIF_TERM atom_esocktype;
-static ERL_NIF_TERM atom_esystem;
+/* *** Local atoms *** */
+
+#define LOCAL_ATOMS \
+ LOCAL_ATOM_DECL(address_info); \
+ LOCAL_ATOM_DECL(debug); \
+ LOCAL_ATOM_DECL(host); \
+ LOCAL_ATOM_DECL(idn); \
+ LOCAL_ATOM_DECL(idna_allow_unassigned); \
+ LOCAL_ATOM_DECL(idna_use_std3_ascii_rules); \
+ LOCAL_ATOM_DECL(namereqd); \
+ LOCAL_ATOM_DECL(name_info); \
+ LOCAL_ATOM_DECL(nofqdn); \
+ LOCAL_ATOM_DECL(numerichost); \
+ LOCAL_ATOM_DECL(numericserv); \
+ LOCAL_ATOM_DECL(service);
+
+#define LOCAL_ERROR_REASON_ATOMS \
+ LOCAL_ATOM_DECL(eaddrfamily); \
+ LOCAL_ATOM_DECL(ebadflags); \
+ LOCAL_ATOM_DECL(efail); \
+ LOCAL_ATOM_DECL(efamily); \
+ LOCAL_ATOM_DECL(efault); \
+ LOCAL_ATOM_DECL(emem); \
+ LOCAL_ATOM_DECL(enametoolong); \
+ LOCAL_ATOM_DECL(enodata); \
+ LOCAL_ATOM_DECL(enoname); \
+ LOCAL_ATOM_DECL(enxio); \
+ LOCAL_ATOM_DECL(eoverflow); \
+ LOCAL_ATOM_DECL(eservice); \
+ LOCAL_ATOM_DECL(esocktype); \
+ LOCAL_ATOM_DECL(esystem);
+
+#define LOCAL_ATOM_DECL(A) static ERL_NIF_TERM atom_##A
+LOCAL_ATOMS
+LOCAL_ERROR_REASON_ATOMS
+#undef LOCAL_ATOM_DECL
/* *** net *** */
@@ -1651,35 +1629,10 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
NDBG( ("NET", "on_load -> entry\r\n") );
#endif
- /* +++ Misc atoms +++ */
- atom_address_info = MKA(env, str_address_info);
- atom_debug = MKA(env, str_debug);
- atom_host = MKA(env, "host");
- atom_idn = MKA(env, str_idn);
- atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned);
- atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules);
- atom_namereqd = MKA(env, str_namereqd);
- atom_name_info = MKA(env, str_name_info);
- atom_nofqdn = MKA(env, str_nofqdn);
- atom_numerichost = MKA(env, str_numerichost);
- atom_numericserv = MKA(env, str_numericserv);
- atom_service = MKA(env, "service");
-
- /* Error codes */
- atom_eaddrfamily = MKA(env, str_eaddrfamily);
- atom_ebadflags = MKA(env, str_ebadflags);
- atom_efail = MKA(env, str_efail);
- atom_efamily = MKA(env, str_efamily);
- atom_efault = MKA(env, str_efault);
- atom_emem = MKA(env, str_emem);
- atom_enametoolong = MKA(env, str_enametoolong);
- atom_enodata = MKA(env, str_enodata);
- atom_enoname = MKA(env, str_enoname);
- atom_enxio = MKA(env, str_enxio);
- atom_eoverflow = MKA(env, str_eoverflow);
- atom_eservice = MKA(env, str_eservice);
- atom_esocktype = MKA(env, str_esocktype);
- atom_esystem = MKA(env, str_esystem);
+#define LOCAL_ATOM_DECL(A) atom_##A = MKA(env, #A)
+LOCAL_ATOMS
+LOCAL_ERROR_REASON_ATOMS
+#undef LOCAL_ATOM_DECL
// For storing "global" things...
// data.env = enif_alloc_env(); // We should really check
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index a9e83adc21..043303a60d 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -103,209 +103,218 @@ typedef unsigned int BOOLEAN_T;
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* "Global" atoms
*/
-extern ERL_NIF_TERM esock_atom_abort;
-extern ERL_NIF_TERM esock_atom_accept;
-extern ERL_NIF_TERM esock_atom_acceptconn;
-extern ERL_NIF_TERM esock_atom_acceptfilter;
-extern ERL_NIF_TERM esock_atom_adaption_layer;
-extern ERL_NIF_TERM esock_atom_addr;
-extern ERL_NIF_TERM esock_atom_addrform;
-extern ERL_NIF_TERM esock_atom_add_membership;
-extern ERL_NIF_TERM esock_atom_add_source_membership;
-extern ERL_NIF_TERM esock_atom_any;
-extern ERL_NIF_TERM esock_atom_associnfo;
-extern ERL_NIF_TERM esock_atom_authhdr;
-extern ERL_NIF_TERM esock_atom_auth_active_key;
-extern ERL_NIF_TERM esock_atom_auth_asconf;
-extern ERL_NIF_TERM esock_atom_auth_chunk;
-extern ERL_NIF_TERM esock_atom_auth_delete_key;
-extern ERL_NIF_TERM esock_atom_auth_key;
-extern ERL_NIF_TERM esock_atom_auth_level;
-extern ERL_NIF_TERM esock_atom_autoclose;
-extern ERL_NIF_TERM esock_atom_bindtodevice;
-extern ERL_NIF_TERM esock_atom_block_source;
-extern ERL_NIF_TERM esock_atom_broadcast;
-extern ERL_NIF_TERM esock_atom_busy_poll;
-extern ERL_NIF_TERM esock_atom_checksum;
-extern ERL_NIF_TERM esock_atom_close;
-extern ERL_NIF_TERM esock_atom_connect;
-extern ERL_NIF_TERM esock_atom_congestion;
-extern ERL_NIF_TERM esock_atom_context;
-extern ERL_NIF_TERM esock_atom_cork;
-extern ERL_NIF_TERM esock_atom_credentials;
-extern ERL_NIF_TERM esock_atom_ctrl;
-extern ERL_NIF_TERM esock_atom_ctrunc;
-extern ERL_NIF_TERM esock_atom_data;
-extern ERL_NIF_TERM esock_atom_debug;
-extern ERL_NIF_TERM esock_atom_default_send_params;
-extern ERL_NIF_TERM esock_atom_delayed_ack_time;
-extern ERL_NIF_TERM esock_atom_dgram;
-extern ERL_NIF_TERM esock_atom_disable_fragments;
-extern ERL_NIF_TERM esock_atom_domain;
-extern ERL_NIF_TERM esock_atom_dontfrag;
-extern ERL_NIF_TERM esock_atom_dontroute;
-extern ERL_NIF_TERM esock_atom_drop_membership;
-extern ERL_NIF_TERM esock_atom_drop_source_membership;
-extern ERL_NIF_TERM esock_atom_dstopts;
-extern ERL_NIF_TERM esock_atom_eor;
-extern ERL_NIF_TERM esock_atom_error;
-extern ERL_NIF_TERM esock_atom_errqueue;
-extern ERL_NIF_TERM esock_atom_esp_network_level;
-extern ERL_NIF_TERM esock_atom_esp_trans_level;
-extern ERL_NIF_TERM esock_atom_events;
-extern ERL_NIF_TERM esock_atom_explicit_eor;
-extern ERL_NIF_TERM esock_atom_faith;
-extern ERL_NIF_TERM esock_atom_false;
-extern ERL_NIF_TERM esock_atom_family;
-extern ERL_NIF_TERM esock_atom_flags;
-extern ERL_NIF_TERM esock_atom_flowinfo;
-extern ERL_NIF_TERM esock_atom_fragment_interleave;
-extern ERL_NIF_TERM esock_atom_freebind;
-extern ERL_NIF_TERM esock_atom_get_peer_addr_info;
-extern ERL_NIF_TERM esock_atom_hdrincl;
-extern ERL_NIF_TERM esock_atom_hmac_ident;
-extern ERL_NIF_TERM esock_atom_hoplimit;
-extern ERL_NIF_TERM esock_atom_hopopts;
-extern ERL_NIF_TERM esock_atom_ifindex;
-extern ERL_NIF_TERM esock_atom_inet;
-extern ERL_NIF_TERM esock_atom_inet6;
-extern ERL_NIF_TERM esock_atom_info;
-extern ERL_NIF_TERM esock_atom_initmsg;
-extern ERL_NIF_TERM esock_atom_iov;
-extern ERL_NIF_TERM esock_atom_ip;
-extern ERL_NIF_TERM esock_atom_ipcomp_level;
-extern ERL_NIF_TERM esock_atom_ipv6;
-extern ERL_NIF_TERM esock_atom_i_want_mapped_v4_addr;
-extern ERL_NIF_TERM esock_atom_join_group;
-extern ERL_NIF_TERM esock_atom_keepalive;
-extern ERL_NIF_TERM esock_atom_keepcnt;
-extern ERL_NIF_TERM esock_atom_keepidle;
-extern ERL_NIF_TERM esock_atom_keepintvl;
-extern ERL_NIF_TERM esock_atom_leave_group;
-extern ERL_NIF_TERM esock_atom_level;
-extern ERL_NIF_TERM esock_atom_linger;
-extern ERL_NIF_TERM esock_atom_local;
-extern ERL_NIF_TERM esock_atom_local_auth_chunks;
-extern ERL_NIF_TERM esock_atom_loopback;
-extern ERL_NIF_TERM esock_atom_lowdelay;
-extern ERL_NIF_TERM esock_atom_mark;
-extern ERL_NIF_TERM esock_atom_maxburst;
-extern ERL_NIF_TERM esock_atom_maxseg;
-extern ERL_NIF_TERM esock_atom_md5sig;
-extern ERL_NIF_TERM esock_atom_mincost;
-extern ERL_NIF_TERM esock_atom_minttl;
-extern ERL_NIF_TERM esock_atom_msfilter;
-extern ERL_NIF_TERM esock_atom_mtu;
-extern ERL_NIF_TERM esock_atom_mtu_discover;
-extern ERL_NIF_TERM esock_atom_multicast_all;
-extern ERL_NIF_TERM esock_atom_multicast_hops;
-extern ERL_NIF_TERM esock_atom_multicast_if;
-extern ERL_NIF_TERM esock_atom_multicast_loop;
-extern ERL_NIF_TERM esock_atom_multicast_ttl;
-extern ERL_NIF_TERM esock_atom_nodelay;
-extern ERL_NIF_TERM esock_atom_nodefrag;
-extern ERL_NIF_TERM esock_atom_noopt;
-extern ERL_NIF_TERM esock_atom_nopush;
-extern ERL_NIF_TERM esock_atom_not_found;
-extern ERL_NIF_TERM esock_atom_not_owner;
-extern ERL_NIF_TERM esock_atom_ok;
-extern ERL_NIF_TERM esock_atom_oob;
-extern ERL_NIF_TERM esock_atom_oobinline;
-extern ERL_NIF_TERM esock_atom_options;
-extern ERL_NIF_TERM esock_atom_origdstaddr;
-extern ERL_NIF_TERM esock_atom_partial_delivery_point;
-extern ERL_NIF_TERM esock_atom_passcred;
-extern ERL_NIF_TERM esock_atom_path;
-extern ERL_NIF_TERM esock_atom_peekcred;
-extern ERL_NIF_TERM esock_atom_peek_off;
-extern ERL_NIF_TERM esock_atom_peer_addr_params;
-extern ERL_NIF_TERM esock_atom_peer_auth_chunks;
-extern ERL_NIF_TERM esock_atom_pktinfo;
-extern ERL_NIF_TERM esock_atom_pktoptions;
-extern ERL_NIF_TERM esock_atom_port;
-extern ERL_NIF_TERM esock_atom_portrange;
-extern ERL_NIF_TERM esock_atom_primary_addr;
-extern ERL_NIF_TERM esock_atom_priority;
-extern ERL_NIF_TERM esock_atom_protocol;
-extern ERL_NIF_TERM esock_atom_raw;
-extern ERL_NIF_TERM esock_atom_rcvbuf;
-extern ERL_NIF_TERM esock_atom_rcvbufforce;
-extern ERL_NIF_TERM esock_atom_rcvlowat;
-extern ERL_NIF_TERM esock_atom_rcvtimeo;
-extern ERL_NIF_TERM esock_atom_rdm;
-extern ERL_NIF_TERM esock_atom_recv;
-extern ERL_NIF_TERM esock_atom_recvdstaddr;
-extern ERL_NIF_TERM esock_atom_recverr;
-extern ERL_NIF_TERM esock_atom_recvfrom;
-extern ERL_NIF_TERM esock_atom_recvif;
-extern ERL_NIF_TERM esock_atom_recvmsg;
-extern ERL_NIF_TERM esock_atom_recvopts;
-extern ERL_NIF_TERM esock_atom_recvorigdstaddr;
-extern ERL_NIF_TERM esock_atom_recvpktinfo;
-extern ERL_NIF_TERM esock_atom_recvtclass;
-extern ERL_NIF_TERM esock_atom_recvtos;
-extern ERL_NIF_TERM esock_atom_recvttl;
-extern ERL_NIF_TERM esock_atom_reliability;
-extern ERL_NIF_TERM esock_atom_reset_streams;
-extern ERL_NIF_TERM esock_atom_retopts;
-extern ERL_NIF_TERM esock_atom_reuseaddr;
-extern ERL_NIF_TERM esock_atom_reuseport;
-extern ERL_NIF_TERM esock_atom_rights;
-extern ERL_NIF_TERM esock_atom_router_alert;
-extern ERL_NIF_TERM esock_atom_rthdr;
-extern ERL_NIF_TERM esock_atom_rtoinfo;
-extern ERL_NIF_TERM esock_atom_rxq_ovfl;
-extern ERL_NIF_TERM esock_atom_scope_id;
-extern ERL_NIF_TERM esock_atom_sctp;
-extern ERL_NIF_TERM esock_atom_sec;
-extern ERL_NIF_TERM esock_atom_select_failed;
-extern ERL_NIF_TERM esock_atom_select_sent;
-extern ERL_NIF_TERM esock_atom_send;
-extern ERL_NIF_TERM esock_atom_sendmsg;
-extern ERL_NIF_TERM esock_atom_sendsrcaddr;
-extern ERL_NIF_TERM esock_atom_sendto;
-extern ERL_NIF_TERM esock_atom_seqpacket;
-extern ERL_NIF_TERM esock_atom_setfib;
-extern ERL_NIF_TERM esock_atom_set_peer_primary_addr;
-extern ERL_NIF_TERM esock_atom_sndbuf;
-extern ERL_NIF_TERM esock_atom_sndbufforce;
-extern ERL_NIF_TERM esock_atom_sndlowat;
-extern ERL_NIF_TERM esock_atom_sndtimeo;
-extern ERL_NIF_TERM esock_atom_socket;
-extern ERL_NIF_TERM esock_atom_socket_tag;
-extern ERL_NIF_TERM esock_atom_spec_dst;
-extern ERL_NIF_TERM esock_atom_status;
-extern ERL_NIF_TERM esock_atom_stream;
-extern ERL_NIF_TERM esock_atom_syncnt;
-extern ERL_NIF_TERM esock_atom_tclass;
-extern ERL_NIF_TERM esock_atom_tcp;
-extern ERL_NIF_TERM esock_atom_throughput;
-extern ERL_NIF_TERM esock_atom_timestamp;
-extern ERL_NIF_TERM esock_atom_tos;
-extern ERL_NIF_TERM esock_atom_transparent;
-extern ERL_NIF_TERM esock_atom_true;
-extern ERL_NIF_TERM esock_atom_trunc;
-extern ERL_NIF_TERM esock_atom_ttl;
-extern ERL_NIF_TERM esock_atom_type;
-extern ERL_NIF_TERM esock_atom_udp;
-extern ERL_NIF_TERM esock_atom_unblock_source;
-extern ERL_NIF_TERM esock_atom_undefined;
-extern ERL_NIF_TERM esock_atom_unicast_hops;
-extern ERL_NIF_TERM esock_atom_unknown;
-extern ERL_NIF_TERM esock_atom_usec;
-extern ERL_NIF_TERM esock_atom_user_timeout;
-extern ERL_NIF_TERM esock_atom_use_ext_recvinfo;
-extern ERL_NIF_TERM esock_atom_use_min_mtu;
-extern ERL_NIF_TERM esock_atom_v6only;
+
+#define GLOBAL_ATOM_DEFS \
+ GLOBAL_ATOM_DEF(abort); \
+ GLOBAL_ATOM_DEF(accept); \
+ GLOBAL_ATOM_DEF(acceptconn); \
+ GLOBAL_ATOM_DEF(acceptfilter); \
+ GLOBAL_ATOM_DEF(adaption_layer); \
+ GLOBAL_ATOM_DEF(addr); \
+ GLOBAL_ATOM_DEF(addrform); \
+ GLOBAL_ATOM_DEF(add_membership); \
+ GLOBAL_ATOM_DEF(add_source_membership); \
+ GLOBAL_ATOM_DEF(any); \
+ GLOBAL_ATOM_DEF(associnfo); \
+ GLOBAL_ATOM_DEF(authhdr); \
+ GLOBAL_ATOM_DEF(auth_active_key); \
+ GLOBAL_ATOM_DEF(auth_asconf); \
+ GLOBAL_ATOM_DEF(auth_chunk); \
+ GLOBAL_ATOM_DEF(auth_delete_key); \
+ GLOBAL_ATOM_DEF(auth_key); \
+ GLOBAL_ATOM_DEF(auth_level); \
+ GLOBAL_ATOM_DEF(autoclose); \
+ GLOBAL_ATOM_DEF(bindtodevice); \
+ GLOBAL_ATOM_DEF(block_source); \
+ GLOBAL_ATOM_DEF(broadcast); \
+ GLOBAL_ATOM_DEF(busy_poll); \
+ GLOBAL_ATOM_DEF(checksum); \
+ GLOBAL_ATOM_DEF(close); \
+ GLOBAL_ATOM_DEF(connect); \
+ GLOBAL_ATOM_DEF(congestion); \
+ GLOBAL_ATOM_DEF(context); \
+ GLOBAL_ATOM_DEF(cork); \
+ GLOBAL_ATOM_DEF(credentials); \
+ GLOBAL_ATOM_DEF(ctrl); \
+ GLOBAL_ATOM_DEF(ctrunc); \
+ GLOBAL_ATOM_DEF(data); \
+ GLOBAL_ATOM_DEF(debug); \
+ GLOBAL_ATOM_DEF(default_send_params); \
+ GLOBAL_ATOM_DEF(delayed_ack_time); \
+ GLOBAL_ATOM_DEF(dgram); \
+ GLOBAL_ATOM_DEF(disable_fragments); \
+ GLOBAL_ATOM_DEF(domain); \
+ GLOBAL_ATOM_DEF(dontfrag); \
+ GLOBAL_ATOM_DEF(dontroute); \
+ GLOBAL_ATOM_DEF(drop_membership); \
+ GLOBAL_ATOM_DEF(drop_source_membership); \
+ GLOBAL_ATOM_DEF(dstopts); \
+ GLOBAL_ATOM_DEF(eor); \
+ GLOBAL_ATOM_DEF(error); \
+ GLOBAL_ATOM_DEF(errqueue); \
+ GLOBAL_ATOM_DEF(esp_network_level); \
+ GLOBAL_ATOM_DEF(esp_trans_level); \
+ GLOBAL_ATOM_DEF(events); \
+ GLOBAL_ATOM_DEF(explicit_eor); \
+ GLOBAL_ATOM_DEF(faith); \
+ GLOBAL_ATOM_DEF(false); \
+ GLOBAL_ATOM_DEF(family); \
+ GLOBAL_ATOM_DEF(flags); \
+ GLOBAL_ATOM_DEF(flowinfo); \
+ GLOBAL_ATOM_DEF(fragment_interleave); \
+ GLOBAL_ATOM_DEF(freebind); \
+ GLOBAL_ATOM_DEF(get_peer_addr_info); \
+ GLOBAL_ATOM_DEF(hdrincl); \
+ GLOBAL_ATOM_DEF(hmac_ident); \
+ GLOBAL_ATOM_DEF(hoplimit); \
+ GLOBAL_ATOM_DEF(hopopts); \
+ GLOBAL_ATOM_DEF(ifindex); \
+ GLOBAL_ATOM_DEF(inet); \
+ GLOBAL_ATOM_DEF(inet6); \
+ GLOBAL_ATOM_DEF(info); \
+ GLOBAL_ATOM_DEF(initmsg); \
+ GLOBAL_ATOM_DEF(iov); \
+ GLOBAL_ATOM_DEF(ip); \
+ GLOBAL_ATOM_DEF(ipcomp_level); \
+ GLOBAL_ATOM_DEF(ipv6); \
+ GLOBAL_ATOM_DEF(i_want_mapped_v4_addr); \
+ GLOBAL_ATOM_DEF(join_group); \
+ GLOBAL_ATOM_DEF(keepalive); \
+ GLOBAL_ATOM_DEF(keepcnt); \
+ GLOBAL_ATOM_DEF(keepidle); \
+ GLOBAL_ATOM_DEF(keepintvl); \
+ GLOBAL_ATOM_DEF(leave_group); \
+ GLOBAL_ATOM_DEF(level); \
+ GLOBAL_ATOM_DEF(linger); \
+ GLOBAL_ATOM_DEF(local); \
+ GLOBAL_ATOM_DEF(local_auth_chunks); \
+ GLOBAL_ATOM_DEF(loopback); \
+ GLOBAL_ATOM_DEF(lowdelay); \
+ GLOBAL_ATOM_DEF(mark); \
+ GLOBAL_ATOM_DEF(maxburst); \
+ GLOBAL_ATOM_DEF(maxseg); \
+ GLOBAL_ATOM_DEF(md5sig); \
+ GLOBAL_ATOM_DEF(mincost); \
+ GLOBAL_ATOM_DEF(minttl); \
+ GLOBAL_ATOM_DEF(msfilter); \
+ GLOBAL_ATOM_DEF(mtu); \
+ GLOBAL_ATOM_DEF(mtu_discover); \
+ GLOBAL_ATOM_DEF(multicast_all); \
+ GLOBAL_ATOM_DEF(multicast_hops); \
+ GLOBAL_ATOM_DEF(multicast_if); \
+ GLOBAL_ATOM_DEF(multicast_loop); \
+ GLOBAL_ATOM_DEF(multicast_ttl); \
+ GLOBAL_ATOM_DEF(nodelay); \
+ GLOBAL_ATOM_DEF(nodefrag); \
+ GLOBAL_ATOM_DEF(noopt); \
+ GLOBAL_ATOM_DEF(nopush); \
+ GLOBAL_ATOM_DEF(not_found); \
+ GLOBAL_ATOM_DEF(not_owner); \
+ GLOBAL_ATOM_DEF(ok); \
+ GLOBAL_ATOM_DEF(oob); \
+ GLOBAL_ATOM_DEF(oobinline); \
+ GLOBAL_ATOM_DEF(options); \
+ GLOBAL_ATOM_DEF(origdstaddr); \
+ GLOBAL_ATOM_DEF(partial_delivery_point); \
+ GLOBAL_ATOM_DEF(passcred); \
+ GLOBAL_ATOM_DEF(path); \
+ GLOBAL_ATOM_DEF(peekcred); \
+ GLOBAL_ATOM_DEF(peek_off); \
+ GLOBAL_ATOM_DEF(peer_addr_params); \
+ GLOBAL_ATOM_DEF(peer_auth_chunks); \
+ GLOBAL_ATOM_DEF(pktinfo); \
+ GLOBAL_ATOM_DEF(pktoptions); \
+ GLOBAL_ATOM_DEF(port); \
+ GLOBAL_ATOM_DEF(portrange); \
+ GLOBAL_ATOM_DEF(primary_addr); \
+ GLOBAL_ATOM_DEF(priority); \
+ GLOBAL_ATOM_DEF(protocol); \
+ GLOBAL_ATOM_DEF(raw); \
+ GLOBAL_ATOM_DEF(rcvbuf); \
+ GLOBAL_ATOM_DEF(rcvbufforce); \
+ GLOBAL_ATOM_DEF(rcvlowat); \
+ GLOBAL_ATOM_DEF(rcvtimeo); \
+ GLOBAL_ATOM_DEF(rdm); \
+ GLOBAL_ATOM_DEF(recv); \
+ GLOBAL_ATOM_DEF(recvdstaddr); \
+ GLOBAL_ATOM_DEF(recverr); \
+ GLOBAL_ATOM_DEF(recvfrom); \
+ GLOBAL_ATOM_DEF(recvif); \
+ GLOBAL_ATOM_DEF(recvmsg); \
+ GLOBAL_ATOM_DEF(recvopts); \
+ GLOBAL_ATOM_DEF(recvorigdstaddr); \
+ GLOBAL_ATOM_DEF(recvpktinfo); \
+ GLOBAL_ATOM_DEF(recvtclass); \
+ GLOBAL_ATOM_DEF(recvtos); \
+ GLOBAL_ATOM_DEF(recvttl); \
+ GLOBAL_ATOM_DEF(reliability); \
+ GLOBAL_ATOM_DEF(reset_streams); \
+ GLOBAL_ATOM_DEF(retopts); \
+ GLOBAL_ATOM_DEF(reuseaddr); \
+ GLOBAL_ATOM_DEF(reuseport); \
+ GLOBAL_ATOM_DEF(rights); \
+ GLOBAL_ATOM_DEF(router_alert); \
+ GLOBAL_ATOM_DEF(rthdr); \
+ GLOBAL_ATOM_DEF(rtoinfo); \
+ GLOBAL_ATOM_DEF(rxq_ovfl); \
+ GLOBAL_ATOM_DEF(scope_id); \
+ GLOBAL_ATOM_DEF(sctp); \
+ GLOBAL_ATOM_DEF(sec); \
+ GLOBAL_ATOM_DEF(select_failed); \
+ GLOBAL_ATOM_DEF(select_sent); \
+ GLOBAL_ATOM_DEF(send); \
+ GLOBAL_ATOM_DEF(sendmsg); \
+ GLOBAL_ATOM_DEF(sendsrcaddr); \
+ GLOBAL_ATOM_DEF(sendto); \
+ GLOBAL_ATOM_DEF(seqpacket); \
+ GLOBAL_ATOM_DEF(setfib); \
+ GLOBAL_ATOM_DEF(set_peer_primary_addr); \
+ GLOBAL_ATOM_DEF(sndbuf); \
+ GLOBAL_ATOM_DEF(sndbufforce); \
+ GLOBAL_ATOM_DEF(sndlowat); \
+ GLOBAL_ATOM_DEF(sndtimeo); \
+ GLOBAL_ATOM_DEF(socket); \
+ GLOBAL_ATOM_DEF(socket_tag); \
+ GLOBAL_ATOM_DEF(spec_dst); \
+ GLOBAL_ATOM_DEF(status); \
+ GLOBAL_ATOM_DEF(stream); \
+ GLOBAL_ATOM_DEF(syncnt); \
+ GLOBAL_ATOM_DEF(tclass); \
+ GLOBAL_ATOM_DEF(tcp); \
+ GLOBAL_ATOM_DEF(throughput); \
+ GLOBAL_ATOM_DEF(timestamp); \
+ GLOBAL_ATOM_DEF(tos); \
+ GLOBAL_ATOM_DEF(transparent); \
+ GLOBAL_ATOM_DEF(true); \
+ GLOBAL_ATOM_DEF(trunc); \
+ GLOBAL_ATOM_DEF(ttl); \
+ GLOBAL_ATOM_DEF(type); \
+ GLOBAL_ATOM_DEF(udp); \
+ GLOBAL_ATOM_DEF(unblock_source); \
+ GLOBAL_ATOM_DEF(undefined); \
+ GLOBAL_ATOM_DEF(unicast_hops); \
+ GLOBAL_ATOM_DEF(unknown); \
+ GLOBAL_ATOM_DEF(usec); \
+ GLOBAL_ATOM_DEF(user_timeout); \
+ GLOBAL_ATOM_DEF(use_ext_recvinfo); \
+ GLOBAL_ATOM_DEF(use_min_mtu); \
+ GLOBAL_ATOM_DEF(v6only);
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- * Error value (=reason) atoms
+ * Error reason atoms
*/
-extern ERL_NIF_TERM esock_atom_eafnosupport;
-extern ERL_NIF_TERM esock_atom_eagain;
-extern ERL_NIF_TERM esock_atom_einval;
+#define GLOBAL_ERROR_REASON_ATOM_DEFS \
+ GLOBAL_ATOM_DEF(eafnosupport); \
+ GLOBAL_ATOM_DEF(eagain); \
+ GLOBAL_ATOM_DEF(einval);
+
+
+#define GLOBAL_ATOM_DEF(A) extern ERL_NIF_TERM esock_atom_##A
+GLOBAL_ATOM_DEFS
+GLOBAL_ERROR_REASON_ATOM_DEFS
+#undef GLOBAL_ATOM_DEF
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -343,14 +352,13 @@ extern ERL_NIF_TERM esock_atom_einval;
#define MLOCK(M) enif_mutex_lock((M))
#define MUNLOCK(M) enif_mutex_unlock((M))
-// #define MONP(S,E,D,P,M) enif_monitor_process((E), (D), (P), (M))
-// #define DEMONP(S,E,D,M) enif_demonitor_process((E), (D), (M))
#define MONP(S,E,D,P,M) esock_monitor((S), (E), (D), (P), (M))
#define DEMONP(S,E,D,M) esock_demonitor((S), (E), (D), (M))
#define MON_INIT(M) esock_monitor_init((M))
-// #define MON_COMP(M1, M2) esock_monitor_compare((M1), (M2))
+#define MON2T(E, M) enif_make_monitor_term((E), (M))
-#define COMPARE(A, B) enif_compare((A), (B))
+#define COMPARE(A, B) enif_compare((A), (B))
+#define COMPARE_PIDS(P1, P2) enif_compare_pids((P1), (P2))
#define IS_ATOM(E, TE) enif_is_atom((E), (TE))
#define IS_BIN(E, TE) enif_is_binary((E), (TE))
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index d56b70e3fd..bb3df85ea4 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -32,7 +32,7 @@
*
* esock_dbg_printf("DEMONP", "[%d] %s: %T\r\n",
* descP->sock, slogan,
- * my_make_monitor_term(env, &monP->mon));
+ * MON2T(env, &monP->mon));
*
*/
@@ -392,6 +392,13 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
#endif
+#if defined(TCP_CONGESTION) || defined(SO_BINDTODEVICE)
+#define USE_GETOPT_STR_OPT
+#define USE_SETOPT_STR_OPT
+#endif
+
+
+
/* *** Socket state defs *** */
#define SOCKET_FLAG_OPEN 0x0001
@@ -882,81 +889,81 @@ typedef struct {
*/
+extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */
-static ERL_NIF_TERM nif_info(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_supports(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-/*
-This is a *global* debug function (enable or disable for all
-operations and all sockets.
-static ERL_NIF_TERM nif_debug(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-*/
-static ERL_NIF_TERM nif_open(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_bind(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_connect(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_listen(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_accept(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_send(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_recv(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
- int argc,
+
+/* All the nif "callback" functions for the socket API has
+ * the exact same API:
+ *
+ * nif_<funcname>(ErlNifEnv* env,
+ * int argc,
+ * const ERL_NIF_TERM argv[]);
+ *
+ * So, to simplify, use some macro magic to define those.
+ *
+ * These are the functions making up the "official" API.
+ * Basically, these functions does some preliminary checks and argument
+ * extractions and then call the functions called 'n<funcname>', which
+ * does the actual work. Except for the info function.
+ *
+ * nif_info
+ * nif_supports
+ * nif_open
+ * nif_bind
+ * nif_connect
+ * nif_listen
+ * nif_accept
+ * nif_send
+ * nif_sendto
+ * nif_sendmsg
+ * nif_recv
+ * nif_recvfrom
+ * nif_recvmsg
+ * nif_close
+ * nif_shutdown
+ * nif_setopt
+ * nif_getopt
+ * nif_sockname
+ * nif_peername
+ * nif_finalize_connection
+ * nif_finalize_close
+ * nif_cancel
+ */
+
+#define ESOCK_NIF_FUNCS \
+ ESOCK_NIF_FUNC_DEF(info); \
+ ESOCK_NIF_FUNC_DEF(supports); \
+ ESOCK_NIF_FUNC_DEF(open); \
+ ESOCK_NIF_FUNC_DEF(bind); \
+ ESOCK_NIF_FUNC_DEF(connect); \
+ ESOCK_NIF_FUNC_DEF(listen); \
+ ESOCK_NIF_FUNC_DEF(accept); \
+ ESOCK_NIF_FUNC_DEF(send); \
+ ESOCK_NIF_FUNC_DEF(sendto); \
+ ESOCK_NIF_FUNC_DEF(sendmsg); \
+ ESOCK_NIF_FUNC_DEF(recv); \
+ ESOCK_NIF_FUNC_DEF(recvfrom); \
+ ESOCK_NIF_FUNC_DEF(recvmsg); \
+ ESOCK_NIF_FUNC_DEF(close); \
+ ESOCK_NIF_FUNC_DEF(shutdown); \
+ ESOCK_NIF_FUNC_DEF(setopt); \
+ ESOCK_NIF_FUNC_DEF(getopt); \
+ ESOCK_NIF_FUNC_DEF(sockname); \
+ ESOCK_NIF_FUNC_DEF(peername); \
+ ESOCK_NIF_FUNC_DEF(finalize_connection); \
+ ESOCK_NIF_FUNC_DEF(finalize_close); \
+ ESOCK_NIF_FUNC_DEF(cancel);
+
+#define ESOCK_NIF_FUNC_DEF(F) \
+ static ERL_NIF_TERM nif_##F(ErlNifEnv* env, \
+ int argc, \
const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_close(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_peername(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
- int argc,
- const ERL_NIF_TERM argv[]);
+ESOCK_NIF_FUNCS
+#undef ESOCK_NIF_FUNC_DEF
+
+#if !defined(__WIN32__)
+/* And here comes the functions that does the actual work (for the most part) */
static ERL_NIF_TERM nsupports(ErlNifEnv* env, int key);
static ERL_NIF_TERM nsupports_options(ErlNifEnv* env);
static ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env);
@@ -984,6 +991,7 @@ static ERL_NIF_TERM nlisten(ErlNifEnv* env,
int backlog);
static ERL_NIF_TERM naccept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM ref);
static ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1000,17 +1008,21 @@ static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
SocketAddress* remote);
static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM ref);
static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM ref);
static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
SOCKET accSock,
SocketAddress* remote);
static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
SocketDescriptor* descP,
- ERL_NIF_TERM ref,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
int save_errno);
static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1078,28 +1090,34 @@ static ERL_NIF_TERM nsetopt(ErlNifEnv* env,
int level,
int eOpt,
ERL_NIF_TERM eVal);
+
+/* Set OTP level options */
static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
SocketDescriptor* descP,
int eOpt,
ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+/* *** nsetopt_otp_debug ***
+ * *** nsetopt_otp_iow ***
+ * *** nsetopt_otp_ctrl_proc ***
+ * *** nsetopt_otp_rcvbuf ***
+ * *** nsetopt_otp_rcvctrlbuf ***
+ * *** nsetopt_otp_sndctrlbuf ***
+ */
+#define NSETOPT_OTP_FUNCS \
+ NSETOPT_OTP_FUNC_DEF(debug); \
+ NSETOPT_OTP_FUNC_DEF(iow); \
+ NSETOPT_OTP_FUNC_DEF(ctrl_proc); \
+ NSETOPT_OTP_FUNC_DEF(rcvbuf); \
+ NSETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
+ NSETOPT_OTP_FUNC_DEF(sndctrlbuf);
+#define NSETOPT_OTP_FUNC_DEF(F) \
+ static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ERL_NIF_TERM eVal)
+NSETOPT_OTP_FUNCS
+#undef NSETOPT_OTP_FUNC_DEF
+
+/* Set native options */
static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
@@ -1579,29 +1597,38 @@ static ERL_NIF_TERM ngetopt(ErlNifEnv* env,
BOOLEAN_T isOTP,
int level,
ERL_NIF_TERM eOpt);
+
static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
SocketDescriptor* descP,
int eOpt);
-static ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
- SocketDescriptor* descP);
+/* *** ngetopt_otp_debug ***
+ * *** ngetopt_otp_iow ***
+ * *** ngetopt_otp_ctrl_proc ***
+ * *** ngetopt_otp_rcvbuf ***
+ * *** ngetopt_otp_rcvctrlbuf ***
+ * *** ngetopt_otp_sndctrlbuf ***
+ * *** ngetopt_otp_fd ***
+ * *** ngetopt_otp_domain ***
+ * *** ngetopt_otp_type ***
+ * *** ngetopt_otp_protocol ***
+ */
+#define NGETOPT_OTP_FUNCS \
+ NGETOPT_OTP_FUNC_DEF(debug); \
+ NGETOPT_OTP_FUNC_DEF(iow); \
+ NGETOPT_OTP_FUNC_DEF(ctrl_proc); \
+ NGETOPT_OTP_FUNC_DEF(rcvbuf); \
+ NGETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
+ NGETOPT_OTP_FUNC_DEF(sndctrlbuf); \
+ NGETOPT_OTP_FUNC_DEF(fd); \
+ NGETOPT_OTP_FUNC_DEF(domain); \
+ NGETOPT_OTP_FUNC_DEF(type); \
+ NGETOPT_OTP_FUNC_DEF(protocol);
+#define NGETOPT_OTP_FUNC_DEF(F) \
+ static ERL_NIF_TERM ngetopt_otp_##F(ErlNifEnv* env, \
+ SocketDescriptor* descP)
+NGETOPT_OTP_FUNCS
+#undef NGETOPT_OTP_FUNC_DEF
+
static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
@@ -1938,31 +1965,38 @@ static ERL_NIF_TERM npeername(ErlNifEnv* env,
static ERL_NIF_TERM ncancel(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM op,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- SocketDescriptor* descP);
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef);
static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- SocketDescriptor* descP);
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef);
static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- SocketDescriptor* descP);
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef);
static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM opRef);
@@ -1978,12 +2012,14 @@ static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
int smode,
int rmode);
+#if defined(USE_SETOPT_STR_OPT)
static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
int opt,
int max,
ERL_NIF_TERM eVal);
+#endif
static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
@@ -2000,11 +2036,13 @@ static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
int opt,
ERL_NIF_TERM eVal);
+#if defined(USE_GETOPT_STR_OPT)
static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
int opt,
int max);
+#endif
static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
@@ -2037,7 +2075,8 @@ static char* recv_init_current_reader(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM ref);
static ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP);
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef);
static void recv_error_current_reader(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM sockRef,
@@ -2206,6 +2245,7 @@ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env,
static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val);
static void inform_waiting_procs(ErlNifEnv* env,
+ char* role,
SocketDescriptor* descP,
SocketRequestQueue* q,
BOOLEAN_T free,
@@ -2221,11 +2261,6 @@ static BOOLEAN_T verify_is_connected(SocketDescriptor* descP, int* err);
static SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event);
-static int compare_pids(ErlNifEnv* env,
- const ErlNifPid* pid1,
- const ErlNifPid* pid2);
-
-
static BOOLEAN_T edomain2domain(int edomain, int* domain);
static BOOLEAN_T etype2type(int etype, int* type);
@@ -2252,56 +2287,69 @@ static void inc_socket(int domain, int type, int protocol);
static void dec_socket(int domain, int type, int protocol);
-static BOOLEAN_T acceptor_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid);
-static ERL_NIF_TERM acceptor_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref);
-static BOOLEAN_T acceptor_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref);
-static BOOLEAN_T acceptor_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid);
-static BOOLEAN_T writer_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid);
-static ERL_NIF_TERM writer_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref);
-static BOOLEAN_T writer_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref);
-static BOOLEAN_T writer_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid);
+/* *** activate_next_acceptor ***
+ * *** activate_next_writer ***
+ * *** activate_next_reader ***
+ *
+ * All the activate-next functions for acceptor, writer and reader
+ * have exactly the same API, so we apply some macro magic to simplify.
+ * They simply operates on dufferent data structures.
+ *
+ */
-static BOOLEAN_T reader_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid);
-static ERL_NIF_TERM reader_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref);
-static BOOLEAN_T reader_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref);
-static BOOLEAN_T reader_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid);
+#define ACTIVATE_NEXT_FUNCS_DEFS \
+ ACTIVATE_NEXT_FUNC_DEF(acceptor) \
+ ACTIVATE_NEXT_FUNC_DEF(writer) \
+ ACTIVATE_NEXT_FUNC_DEF(reader)
+
+#define ACTIVATE_NEXT_FUNC_DEF(F) \
+ static BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ERL_NIF_TERM sockRef);
+ACTIVATE_NEXT_FUNCS_DEFS
+#undef ACTIVATE_NEXT_FUNC_DEF
+
+static BOOLEAN_T activate_next(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ SocketRequestor* reqP,
+ SocketRequestQueue* q,
+ ERL_NIF_TERM sockRef);
+
+/* *** acceptor_search4pid | writer_search4pid | reader_search4pid ***
+ * *** acceptor_push | writer_push | reader_push ***
+ * *** acceptor_pop | writer_pop | reader_pop ***
+ * *** acceptor_unqueue | writer_unqueue | reader_unqueue ***
+ *
+ * All the queue operator functions (search4pid, push, pop
+ * and unqueue) for acceptor, writer and reader has exactly
+ * the same API, so we apply some macro magic to simplify.
+ */
+
+#define ESOCK_OPERATOR_FUNCS_DEFS \
+ ESOCK_OPERATOR_FUNCS_DEF(acceptor) \
+ ESOCK_OPERATOR_FUNCS_DEF(writer) \
+ ESOCK_OPERATOR_FUNCS_DEF(reader)
+
+#define ESOCK_OPERATOR_FUNCS_DEF(O) \
+ static BOOLEAN_T O##_search4pid(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ErlNifPid* pid); \
+ static ERL_NIF_TERM O##_push(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ErlNifPid pid, \
+ ERL_NIF_TERM ref); \
+ static BOOLEAN_T O##_pop(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ SocketRequestor* reqP); \
+ static BOOLEAN_T O##_unqueue(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ const ErlNifPid* pid);
+ESOCK_OPERATOR_FUNCS_DEFS
+#undef ESOCK_OPERATOR_FUNCS_DEF
+
+static BOOLEAN_T requestor_pop(SocketRequestQueue* q,
+ SocketRequestor* reqP);
static BOOLEAN_T qsearch4pid(ErlNifEnv* env,
SocketRequestQueue* q,
@@ -2325,11 +2373,8 @@ static int esock_demonitor(const char* slogan,
SocketDescriptor* descP,
ESockMonitor* monP);
static void esock_monitor_init(ESockMonitor* mon);
-/*
-static int esock_monitor_compare(const ErlNifMonitor* mon1,
- const ESockMonitor* mon2);
-*/
+#endif // if defined(__WIN32__)
/*
#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE)
@@ -2346,14 +2391,20 @@ static void socket_down(ErlNifEnv* env,
void* obj,
const ErlNifPid* pid,
const ErlNifMonitor* mon);
+
+#if !defined(__WIN32__)
+
static void socket_down_acceptor(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid);
static void socket_down_writer(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid);
static void socket_down_reader(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid);
static char* esock_send_close_msg(ErlNifEnv* env,
@@ -2397,6 +2448,8 @@ static BOOLEAN_T extract_debug(ErlNifEnv* env,
static BOOLEAN_T extract_iow(ErlNifEnv* env,
ERL_NIF_TERM map);
+#endif // if defined(__WIN32__)
+
static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
@@ -2424,354 +2477,301 @@ static const struct in6_addr in6addr_loopback =
-/* *** String constants *** */
-static char str_adaptation_layer[] = "adaptation_layer";
-static char str_address[] = "address";
-static char str_association[] = "association";
-static char str_assoc_id[] = "assoc_id";
-static char str_authentication[] = "authentication";
-// static char str_any[] = "any";
-static char str_bool[] = "bool";
-static char str_close[] = "close";
-static char str_closed[] = "closed";
-static char str_closing[] = "closing";
-static char str_cookie_life[] = "cookie_life";
-static char str_data_in[] = "data_in";
-static char str_do[] = "do";
-static char str_dont[] = "dont";
-static char str_exclude[] = "exclude";
-static char str_false[] = "false";
-static char str_global_counters[] = "global_counters";
-static char str_in4_sockaddr[] = "in4_sockaddr";
-static char str_in6_sockaddr[] = "in6_sockaddr";
-static char str_include[] = "include";
-static char str_initial[] = "initial";
-static char str_int[] = "int";
-static char str_interface[] = "interface";
-static char str_iow[] = "iow";
-static char str_local_rwnd[] = "local_rwnd";
-// static char str_loopback[] = "loopback";
-static char str_max[] = "max";
-static char str_max_attempts[] = "max_attempts";
-static char str_max_init_timeo[] = "max_init_timeo";
-static char str_max_instreams[] = "max_instreams";
-static char str_max_rxt[] = "max_rxt";
-static char str_min[] = "min";
-static char str_mode[] = "mode";
-static char str_multiaddr[] = "multiaddr";
-// static char str_nif_abort[] = "nif_abort";
-static char str_null[] = "null";
-static char str_num_dlocal[] = "num_domain_local";
-static char str_num_dinet[] = "num_domain_inet";
-static char str_num_dinet6[] = "num_domain_inet6";
-static char str_num_outstreams[] = "num_outstreams";
-static char str_num_peer_dests[] = "num_peer_dests";
-static char str_num_pip[] = "num_proto_ip";
-static char str_num_psctp[] = "num_proto_sctp";
-static char str_num_ptcp[] = "num_proto_tcp";
-static char str_num_pudp[] = "num_proto_udp";
-static char str_num_sockets[] = "num_sockets";
-static char str_num_tdgrams[] = "num_type_dgram";
-static char str_num_tseqpkgs[] = "num_type_seqpacket";
-static char str_num_tstreams[] = "num_type_stream";
-static char str_partial_delivery[] = "partial_delivery";
-static char str_peer_error[] = "peer_error";
-static char str_peer_rwnd[] = "peer_rwnd";
-static char str_probe[] = "probe";
-static char str_select[] = "select";
-static char str_sender_dry[] = "sender_dry";
-static char str_send_failure[] = "send_failure";
-static char str_shutdown[] = "shutdown";
-static char str_slist[] = "slist";
-static char str_sourceaddr[] = "sourceaddr";
-static char str_timeout[] = "timeout";
-static char str_true[] = "true";
-static char str_want[] = "want";
-
/* (special) error string constants */
-static char str_eisconn[] = "eisconn";
-static char str_enotclosing[] = "enotclosing";
-static char str_enotconn[] = "enotconn";
-static char str_exalloc[] = "exalloc";
-static char str_exbadstate[] = "exbadstate";
-static char str_exbusy[] = "exbusy";
static char str_exmon[] = "exmonitor"; // failed monitor
static char str_exself[] = "exself"; // failed self
static char str_exsend[] = "exsend"; // failed send
-/* *** "Global" Atoms *** */
-ERL_NIF_TERM esock_atom_abort;
-ERL_NIF_TERM esock_atom_accept;
-ERL_NIF_TERM esock_atom_acceptconn;
-ERL_NIF_TERM esock_atom_acceptfilter;
-ERL_NIF_TERM esock_atom_adaption_layer;
-ERL_NIF_TERM esock_atom_addr;
-ERL_NIF_TERM esock_atom_addrform;
-ERL_NIF_TERM esock_atom_add_membership;
-ERL_NIF_TERM esock_atom_add_source_membership;
-ERL_NIF_TERM esock_atom_any;
-ERL_NIF_TERM esock_atom_associnfo;
-ERL_NIF_TERM esock_atom_authhdr;
-ERL_NIF_TERM esock_atom_auth_active_key;
-ERL_NIF_TERM esock_atom_auth_asconf;
-ERL_NIF_TERM esock_atom_auth_chunk;
-ERL_NIF_TERM esock_atom_auth_delete_key;
-ERL_NIF_TERM esock_atom_auth_key;
-ERL_NIF_TERM esock_atom_auth_level;
-ERL_NIF_TERM esock_atom_autoclose;
-ERL_NIF_TERM esock_atom_bindtodevice;
-ERL_NIF_TERM esock_atom_block_source;
-ERL_NIF_TERM esock_atom_broadcast;
-ERL_NIF_TERM esock_atom_busy_poll;
-ERL_NIF_TERM esock_atom_checksum;
-ERL_NIF_TERM esock_atom_close;
-ERL_NIF_TERM esock_atom_connect;
-ERL_NIF_TERM esock_atom_congestion;
-ERL_NIF_TERM esock_atom_context;
-ERL_NIF_TERM esock_atom_cork;
-ERL_NIF_TERM esock_atom_credentials;
-ERL_NIF_TERM esock_atom_ctrl;
-ERL_NIF_TERM esock_atom_ctrunc;
-ERL_NIF_TERM esock_atom_data;
-ERL_NIF_TERM esock_atom_debug;
-ERL_NIF_TERM esock_atom_default_send_params;
-ERL_NIF_TERM esock_atom_delayed_ack_time;
-ERL_NIF_TERM esock_atom_dgram;
-ERL_NIF_TERM esock_atom_disable_fragments;
-ERL_NIF_TERM esock_atom_domain;
-ERL_NIF_TERM esock_atom_dontfrag;
-ERL_NIF_TERM esock_atom_dontroute;
-ERL_NIF_TERM esock_atom_drop_membership;
-ERL_NIF_TERM esock_atom_drop_source_membership;
-ERL_NIF_TERM esock_atom_dstopts;
-ERL_NIF_TERM esock_atom_eor;
-ERL_NIF_TERM esock_atom_error;
-ERL_NIF_TERM esock_atom_errqueue;
-ERL_NIF_TERM esock_atom_esp_network_level;
-ERL_NIF_TERM esock_atom_esp_trans_level;
-ERL_NIF_TERM esock_atom_events;
-ERL_NIF_TERM esock_atom_explicit_eor;
-ERL_NIF_TERM esock_atom_faith;
-ERL_NIF_TERM esock_atom_false;
-ERL_NIF_TERM esock_atom_family;
-ERL_NIF_TERM esock_atom_flags;
-ERL_NIF_TERM esock_atom_flowinfo;
-ERL_NIF_TERM esock_atom_fragment_interleave;
-ERL_NIF_TERM esock_atom_freebind;
-ERL_NIF_TERM esock_atom_get_peer_addr_info;
-ERL_NIF_TERM esock_atom_hdrincl;
-ERL_NIF_TERM esock_atom_hmac_ident;
-ERL_NIF_TERM esock_atom_hoplimit;
-ERL_NIF_TERM esock_atom_hopopts;
-ERL_NIF_TERM esock_atom_ifindex;
-ERL_NIF_TERM esock_atom_inet;
-ERL_NIF_TERM esock_atom_inet6;
-ERL_NIF_TERM esock_atom_info;
-ERL_NIF_TERM esock_atom_initmsg;
-ERL_NIF_TERM esock_atom_iov;
-ERL_NIF_TERM esock_atom_ip;
-ERL_NIF_TERM esock_atom_ipcomp_level;
-ERL_NIF_TERM esock_atom_ipv6;
-ERL_NIF_TERM esock_atom_i_want_mapped_v4_addr;
-ERL_NIF_TERM esock_atom_join_group;
-ERL_NIF_TERM esock_atom_keepalive;
-ERL_NIF_TERM esock_atom_keepcnt;
-ERL_NIF_TERM esock_atom_keepidle;
-ERL_NIF_TERM esock_atom_keepintvl;
-ERL_NIF_TERM esock_atom_leave_group;
-ERL_NIF_TERM esock_atom_level;
-ERL_NIF_TERM esock_atom_linger;
-ERL_NIF_TERM esock_atom_local;
-ERL_NIF_TERM esock_atom_local_auth_chunks;
-ERL_NIF_TERM esock_atom_loopback;
-ERL_NIF_TERM esock_atom_lowdelay;
-ERL_NIF_TERM esock_atom_mark;
-ERL_NIF_TERM esock_atom_maxburst;
-ERL_NIF_TERM esock_atom_maxseg;
-ERL_NIF_TERM esock_atom_md5sig;
-ERL_NIF_TERM esock_atom_mincost;
-ERL_NIF_TERM esock_atom_minttl;
-ERL_NIF_TERM esock_atom_msfilter;
-ERL_NIF_TERM esock_atom_mtu;
-ERL_NIF_TERM esock_atom_mtu_discover;
-ERL_NIF_TERM esock_atom_multicast_all;
-ERL_NIF_TERM esock_atom_multicast_hops;
-ERL_NIF_TERM esock_atom_multicast_if;
-ERL_NIF_TERM esock_atom_multicast_loop;
-ERL_NIF_TERM esock_atom_multicast_ttl;
-ERL_NIF_TERM esock_atom_nodelay;
-ERL_NIF_TERM esock_atom_nodefrag;
-ERL_NIF_TERM esock_atom_noopt;
-ERL_NIF_TERM esock_atom_nopush;
-ERL_NIF_TERM esock_atom_not_found;
-ERL_NIF_TERM esock_atom_not_owner;
-ERL_NIF_TERM esock_atom_ok;
-ERL_NIF_TERM esock_atom_oob;
-ERL_NIF_TERM esock_atom_oobinline;
-ERL_NIF_TERM esock_atom_options;
-ERL_NIF_TERM esock_atom_origdstaddr;
-ERL_NIF_TERM esock_atom_partial_delivery_point;
-ERL_NIF_TERM esock_atom_passcred;
-ERL_NIF_TERM esock_atom_path;
-ERL_NIF_TERM esock_atom_peekcred;
-ERL_NIF_TERM esock_atom_peek_off;
-ERL_NIF_TERM esock_atom_peer_addr_params;
-ERL_NIF_TERM esock_atom_peer_auth_chunks;
-ERL_NIF_TERM esock_atom_pktinfo;
-ERL_NIF_TERM esock_atom_pktoptions;
-ERL_NIF_TERM esock_atom_port;
-ERL_NIF_TERM esock_atom_portrange;
-ERL_NIF_TERM esock_atom_primary_addr;
-ERL_NIF_TERM esock_atom_priority;
-ERL_NIF_TERM esock_atom_protocol;
-ERL_NIF_TERM esock_atom_raw;
-ERL_NIF_TERM esock_atom_rcvbuf;
-ERL_NIF_TERM esock_atom_rcvbufforce;
-ERL_NIF_TERM esock_atom_rcvlowat;
-ERL_NIF_TERM esock_atom_rcvtimeo;
-ERL_NIF_TERM esock_atom_rdm;
-ERL_NIF_TERM esock_atom_recv;
-ERL_NIF_TERM esock_atom_recvdstaddr;
-ERL_NIF_TERM esock_atom_recverr;
-ERL_NIF_TERM esock_atom_recvfrom;
-ERL_NIF_TERM esock_atom_recvif;
-ERL_NIF_TERM esock_atom_recvmsg;
-ERL_NIF_TERM esock_atom_recvopts;
-ERL_NIF_TERM esock_atom_recvorigdstaddr;
-ERL_NIF_TERM esock_atom_recvpktinfo;
-ERL_NIF_TERM esock_atom_recvtclass;
-ERL_NIF_TERM esock_atom_recvtos;
-ERL_NIF_TERM esock_atom_recvttl;
-ERL_NIF_TERM esock_atom_reliability;
-ERL_NIF_TERM esock_atom_reset_streams;
-ERL_NIF_TERM esock_atom_retopts;
-ERL_NIF_TERM esock_atom_reuseaddr;
-ERL_NIF_TERM esock_atom_reuseport;
-ERL_NIF_TERM esock_atom_rights;
-ERL_NIF_TERM esock_atom_router_alert;
-ERL_NIF_TERM esock_atom_rthdr;
-ERL_NIF_TERM esock_atom_rtoinfo;
-ERL_NIF_TERM esock_atom_rxq_ovfl;
-ERL_NIF_TERM esock_atom_scope_id;
-ERL_NIF_TERM esock_atom_sctp;
-ERL_NIF_TERM esock_atom_sec;
-ERL_NIF_TERM esock_atom_select_failed;
-ERL_NIF_TERM esock_atom_select_sent;
-ERL_NIF_TERM esock_atom_send;
-ERL_NIF_TERM esock_atom_sendmsg;
-ERL_NIF_TERM esock_atom_sendsrcaddr;
-ERL_NIF_TERM esock_atom_sendto;
-ERL_NIF_TERM esock_atom_seqpacket;
-ERL_NIF_TERM esock_atom_setfib;
-ERL_NIF_TERM esock_atom_set_peer_primary_addr;
-ERL_NIF_TERM esock_atom_socket;
-ERL_NIF_TERM esock_atom_socket_tag;
-ERL_NIF_TERM esock_atom_sndbuf;
-ERL_NIF_TERM esock_atom_sndbufforce;
-ERL_NIF_TERM esock_atom_sndlowat;
-ERL_NIF_TERM esock_atom_sndtimeo;
-ERL_NIF_TERM esock_atom_spec_dst;
-ERL_NIF_TERM esock_atom_status;
-ERL_NIF_TERM esock_atom_stream;
-ERL_NIF_TERM esock_atom_syncnt;
-ERL_NIF_TERM esock_atom_tclass;
-ERL_NIF_TERM esock_atom_tcp;
-ERL_NIF_TERM esock_atom_throughput;
-ERL_NIF_TERM esock_atom_timestamp;
-ERL_NIF_TERM esock_atom_tos;
-ERL_NIF_TERM esock_atom_transparent;
-ERL_NIF_TERM esock_atom_true;
-ERL_NIF_TERM esock_atom_trunc;
-ERL_NIF_TERM esock_atom_ttl;
-ERL_NIF_TERM esock_atom_type;
-ERL_NIF_TERM esock_atom_udp;
-ERL_NIF_TERM esock_atom_unblock_source;
-ERL_NIF_TERM esock_atom_undefined;
-ERL_NIF_TERM esock_atom_unicast_hops;
-ERL_NIF_TERM esock_atom_unknown;
-ERL_NIF_TERM esock_atom_usec;
-ERL_NIF_TERM esock_atom_user_timeout;
-ERL_NIF_TERM esock_atom_use_ext_recvinfo;
-ERL_NIF_TERM esock_atom_use_min_mtu;
-ERL_NIF_TERM esock_atom_v6only;
-
-/* *** "Global" error (=reason) atoms *** */
-ERL_NIF_TERM esock_atom_eagain;
-ERL_NIF_TERM esock_atom_eafnosupport;
-ERL_NIF_TERM esock_atom_einval;
-
-/* *** Atoms *** */
-static ERL_NIF_TERM atom_adaptation_layer;
-static ERL_NIF_TERM atom_address;
-static ERL_NIF_TERM atom_association;
-static ERL_NIF_TERM atom_assoc_id;
-static ERL_NIF_TERM atom_authentication;
-static ERL_NIF_TERM atom_bool;
-static ERL_NIF_TERM atom_close;
-static ERL_NIF_TERM atom_closed;
-static ERL_NIF_TERM atom_closing;
-static ERL_NIF_TERM atom_cookie_life;
-static ERL_NIF_TERM atom_data_in;
-static ERL_NIF_TERM atom_do;
-static ERL_NIF_TERM atom_dont;
-static ERL_NIF_TERM atom_exclude;
-static ERL_NIF_TERM atom_false;
-static ERL_NIF_TERM atom_global_counters;
-static ERL_NIF_TERM atom_in4_sockaddr;
-static ERL_NIF_TERM atom_in6_sockaddr;
-static ERL_NIF_TERM atom_include;
-static ERL_NIF_TERM atom_initial;
-static ERL_NIF_TERM atom_int;
-static ERL_NIF_TERM atom_interface;
-static ERL_NIF_TERM atom_iow;
-static ERL_NIF_TERM atom_local_rwnd;
-static ERL_NIF_TERM atom_max;
-static ERL_NIF_TERM atom_max_attempts;
-static ERL_NIF_TERM atom_max_init_timeo;
-static ERL_NIF_TERM atom_max_instreams;
-static ERL_NIF_TERM atom_max_rxt;
-static ERL_NIF_TERM atom_min;
-static ERL_NIF_TERM atom_mode;
-static ERL_NIF_TERM atom_multiaddr;
-// static ERL_NIF_TERM atom_nif_abort;
-static ERL_NIF_TERM atom_null;
-static ERL_NIF_TERM atom_num_dinet;
-static ERL_NIF_TERM atom_num_dinet6;
-static ERL_NIF_TERM atom_num_dlocal;
-static ERL_NIF_TERM atom_num_outstreams;
-static ERL_NIF_TERM atom_num_peer_dests;
-static ERL_NIF_TERM atom_num_pip;
-static ERL_NIF_TERM atom_num_psctp;
-static ERL_NIF_TERM atom_num_ptcp;
-static ERL_NIF_TERM atom_num_pudp;
-static ERL_NIF_TERM atom_num_sockets;
-static ERL_NIF_TERM atom_num_tdgrams;
-static ERL_NIF_TERM atom_num_tseqpkgs;
-static ERL_NIF_TERM atom_num_tstreams;
-static ERL_NIF_TERM atom_partial_delivery;
-static ERL_NIF_TERM atom_peer_error;
-static ERL_NIF_TERM atom_peer_rwnd;
-static ERL_NIF_TERM atom_probe;
-static ERL_NIF_TERM atom_select;
-static ERL_NIF_TERM atom_sender_dry;
-static ERL_NIF_TERM atom_send_failure;
-static ERL_NIF_TERM atom_shutdown;
-static ERL_NIF_TERM atom_slist;
-static ERL_NIF_TERM atom_sourceaddr;
-static ERL_NIF_TERM atom_timeout;
-static ERL_NIF_TERM atom_true;
-static ERL_NIF_TERM atom_want;
-
-static ERL_NIF_TERM atom_eisconn;
-static ERL_NIF_TERM atom_enotclosing;
-static ERL_NIF_TERM atom_enotconn;
-static ERL_NIF_TERM atom_exalloc;
-static ERL_NIF_TERM atom_exbadstate;
-static ERL_NIF_TERM atom_exbusy;
-static ERL_NIF_TERM atom_exmon;
-static ERL_NIF_TERM atom_exself;
-static ERL_NIF_TERM atom_exsend;
+
+/* *** Global atoms *** */
+#define GLOBAL_ATOMS \
+ GLOBAL_ATOM_DECL(abort); \
+ GLOBAL_ATOM_DECL(accept); \
+ GLOBAL_ATOM_DECL(acceptconn); \
+ GLOBAL_ATOM_DECL(acceptfilter); \
+ GLOBAL_ATOM_DECL(adaption_layer); \
+ GLOBAL_ATOM_DECL(addr); \
+ GLOBAL_ATOM_DECL(addrform); \
+ GLOBAL_ATOM_DECL(add_membership); \
+ GLOBAL_ATOM_DECL(add_source_membership); \
+ GLOBAL_ATOM_DECL(any); \
+ GLOBAL_ATOM_DECL(associnfo); \
+ GLOBAL_ATOM_DECL(authhdr); \
+ GLOBAL_ATOM_DECL(auth_active_key); \
+ GLOBAL_ATOM_DECL(auth_asconf); \
+ GLOBAL_ATOM_DECL(auth_chunk); \
+ GLOBAL_ATOM_DECL(auth_delete_key); \
+ GLOBAL_ATOM_DECL(auth_key); \
+ GLOBAL_ATOM_DECL(auth_level); \
+ GLOBAL_ATOM_DECL(autoclose); \
+ GLOBAL_ATOM_DECL(bindtodevice); \
+ GLOBAL_ATOM_DECL(block_source); \
+ GLOBAL_ATOM_DECL(broadcast); \
+ GLOBAL_ATOM_DECL(busy_poll); \
+ GLOBAL_ATOM_DECL(checksum); \
+ GLOBAL_ATOM_DECL(close); \
+ GLOBAL_ATOM_DECL(connect); \
+ GLOBAL_ATOM_DECL(congestion); \
+ GLOBAL_ATOM_DECL(context); \
+ GLOBAL_ATOM_DECL(cork); \
+ GLOBAL_ATOM_DECL(credentials); \
+ GLOBAL_ATOM_DECL(ctrl); \
+ GLOBAL_ATOM_DECL(ctrunc); \
+ GLOBAL_ATOM_DECL(data); \
+ GLOBAL_ATOM_DECL(debug); \
+ GLOBAL_ATOM_DECL(default_send_params); \
+ GLOBAL_ATOM_DECL(delayed_ack_time); \
+ GLOBAL_ATOM_DECL(dgram); \
+ GLOBAL_ATOM_DECL(disable_fragments); \
+ GLOBAL_ATOM_DECL(domain); \
+ GLOBAL_ATOM_DECL(dontfrag); \
+ GLOBAL_ATOM_DECL(dontroute); \
+ GLOBAL_ATOM_DECL(drop_membership); \
+ GLOBAL_ATOM_DECL(drop_source_membership); \
+ GLOBAL_ATOM_DECL(dstopts); \
+ GLOBAL_ATOM_DECL(eor); \
+ GLOBAL_ATOM_DECL(error); \
+ GLOBAL_ATOM_DECL(errqueue); \
+ GLOBAL_ATOM_DECL(esp_network_level); \
+ GLOBAL_ATOM_DECL(esp_trans_level); \
+ GLOBAL_ATOM_DECL(events); \
+ GLOBAL_ATOM_DECL(explicit_eor); \
+ GLOBAL_ATOM_DECL(faith); \
+ GLOBAL_ATOM_DECL(false); \
+ GLOBAL_ATOM_DECL(family); \
+ GLOBAL_ATOM_DECL(flags); \
+ GLOBAL_ATOM_DECL(flowinfo); \
+ GLOBAL_ATOM_DECL(fragment_interleave); \
+ GLOBAL_ATOM_DECL(freebind); \
+ GLOBAL_ATOM_DECL(get_peer_addr_info); \
+ GLOBAL_ATOM_DECL(hdrincl); \
+ GLOBAL_ATOM_DECL(hmac_ident); \
+ GLOBAL_ATOM_DECL(hoplimit); \
+ GLOBAL_ATOM_DECL(hopopts); \
+ GLOBAL_ATOM_DECL(ifindex); \
+ GLOBAL_ATOM_DECL(inet); \
+ GLOBAL_ATOM_DECL(inet6); \
+ GLOBAL_ATOM_DECL(info); \
+ GLOBAL_ATOM_DECL(initmsg); \
+ GLOBAL_ATOM_DECL(iov); \
+ GLOBAL_ATOM_DECL(ip); \
+ GLOBAL_ATOM_DECL(ipcomp_level); \
+ GLOBAL_ATOM_DECL(ipv6); \
+ GLOBAL_ATOM_DECL(i_want_mapped_v4_addr); \
+ GLOBAL_ATOM_DECL(join_group); \
+ GLOBAL_ATOM_DECL(keepalive); \
+ GLOBAL_ATOM_DECL(keepcnt); \
+ GLOBAL_ATOM_DECL(keepidle); \
+ GLOBAL_ATOM_DECL(keepintvl); \
+ GLOBAL_ATOM_DECL(leave_group); \
+ GLOBAL_ATOM_DECL(level); \
+ GLOBAL_ATOM_DECL(linger); \
+ GLOBAL_ATOM_DECL(local); \
+ GLOBAL_ATOM_DECL(local_auth_chunks); \
+ GLOBAL_ATOM_DECL(loopback); \
+ GLOBAL_ATOM_DECL(lowdelay); \
+ GLOBAL_ATOM_DECL(mark); \
+ GLOBAL_ATOM_DECL(maxburst); \
+ GLOBAL_ATOM_DECL(maxseg); \
+ GLOBAL_ATOM_DECL(md5sig); \
+ GLOBAL_ATOM_DECL(mincost); \
+ GLOBAL_ATOM_DECL(minttl); \
+ GLOBAL_ATOM_DECL(msfilter); \
+ GLOBAL_ATOM_DECL(mtu); \
+ GLOBAL_ATOM_DECL(mtu_discover); \
+ GLOBAL_ATOM_DECL(multicast_all); \
+ GLOBAL_ATOM_DECL(multicast_hops); \
+ GLOBAL_ATOM_DECL(multicast_if); \
+ GLOBAL_ATOM_DECL(multicast_loop); \
+ GLOBAL_ATOM_DECL(multicast_ttl); \
+ GLOBAL_ATOM_DECL(nodelay); \
+ GLOBAL_ATOM_DECL(nodefrag); \
+ GLOBAL_ATOM_DECL(noopt); \
+ GLOBAL_ATOM_DECL(nopush); \
+ GLOBAL_ATOM_DECL(not_found); \
+ GLOBAL_ATOM_DECL(not_owner); \
+ GLOBAL_ATOM_DECL(ok); \
+ GLOBAL_ATOM_DECL(oob); \
+ GLOBAL_ATOM_DECL(oobinline); \
+ GLOBAL_ATOM_DECL(options); \
+ GLOBAL_ATOM_DECL(origdstaddr); \
+ GLOBAL_ATOM_DECL(partial_delivery_point); \
+ GLOBAL_ATOM_DECL(passcred); \
+ GLOBAL_ATOM_DECL(path); \
+ GLOBAL_ATOM_DECL(peekcred); \
+ GLOBAL_ATOM_DECL(peek_off); \
+ GLOBAL_ATOM_DECL(peer_addr_params); \
+ GLOBAL_ATOM_DECL(peer_auth_chunks); \
+ GLOBAL_ATOM_DECL(pktinfo); \
+ GLOBAL_ATOM_DECL(pktoptions); \
+ GLOBAL_ATOM_DECL(port); \
+ GLOBAL_ATOM_DECL(portrange); \
+ GLOBAL_ATOM_DECL(primary_addr); \
+ GLOBAL_ATOM_DECL(priority); \
+ GLOBAL_ATOM_DECL(protocol); \
+ GLOBAL_ATOM_DECL(raw); \
+ GLOBAL_ATOM_DECL(rcvbuf); \
+ GLOBAL_ATOM_DECL(rcvbufforce); \
+ GLOBAL_ATOM_DECL(rcvlowat); \
+ GLOBAL_ATOM_DECL(rcvtimeo); \
+ GLOBAL_ATOM_DECL(rdm); \
+ GLOBAL_ATOM_DECL(recv); \
+ GLOBAL_ATOM_DECL(recvdstaddr); \
+ GLOBAL_ATOM_DECL(recverr); \
+ GLOBAL_ATOM_DECL(recvfrom); \
+ GLOBAL_ATOM_DECL(recvif); \
+ GLOBAL_ATOM_DECL(recvmsg); \
+ GLOBAL_ATOM_DECL(recvopts); \
+ GLOBAL_ATOM_DECL(recvorigdstaddr); \
+ GLOBAL_ATOM_DECL(recvpktinfo); \
+ GLOBAL_ATOM_DECL(recvtclass); \
+ GLOBAL_ATOM_DECL(recvtos); \
+ GLOBAL_ATOM_DECL(recvttl); \
+ GLOBAL_ATOM_DECL(reliability); \
+ GLOBAL_ATOM_DECL(reset_streams); \
+ GLOBAL_ATOM_DECL(retopts); \
+ GLOBAL_ATOM_DECL(reuseaddr); \
+ GLOBAL_ATOM_DECL(reuseport); \
+ GLOBAL_ATOM_DECL(rights); \
+ GLOBAL_ATOM_DECL(router_alert); \
+ GLOBAL_ATOM_DECL(rthdr); \
+ GLOBAL_ATOM_DECL(rtoinfo); \
+ GLOBAL_ATOM_DECL(rxq_ovfl); \
+ GLOBAL_ATOM_DECL(scope_id); \
+ GLOBAL_ATOM_DECL(sctp); \
+ GLOBAL_ATOM_DECL(sec); \
+ GLOBAL_ATOM_DECL(select_failed); \
+ GLOBAL_ATOM_DECL(select_sent); \
+ GLOBAL_ATOM_DECL(send); \
+ GLOBAL_ATOM_DECL(sendmsg); \
+ GLOBAL_ATOM_DECL(sendsrcaddr); \
+ GLOBAL_ATOM_DECL(sendto); \
+ GLOBAL_ATOM_DECL(seqpacket); \
+ GLOBAL_ATOM_DECL(setfib); \
+ GLOBAL_ATOM_DECL(set_peer_primary_addr); \
+ GLOBAL_ATOM_DECL(socket); \
+ GLOBAL_ATOM_DECL(sndbuf); \
+ GLOBAL_ATOM_DECL(sndbufforce); \
+ GLOBAL_ATOM_DECL(sndlowat); \
+ GLOBAL_ATOM_DECL(sndtimeo); \
+ GLOBAL_ATOM_DECL(spec_dst); \
+ GLOBAL_ATOM_DECL(status); \
+ GLOBAL_ATOM_DECL(stream); \
+ GLOBAL_ATOM_DECL(syncnt); \
+ GLOBAL_ATOM_DECL(tclass); \
+ GLOBAL_ATOM_DECL(tcp); \
+ GLOBAL_ATOM_DECL(throughput); \
+ GLOBAL_ATOM_DECL(timestamp); \
+ GLOBAL_ATOM_DECL(tos); \
+ GLOBAL_ATOM_DECL(transparent); \
+ GLOBAL_ATOM_DECL(true); \
+ GLOBAL_ATOM_DECL(trunc); \
+ GLOBAL_ATOM_DECL(ttl); \
+ GLOBAL_ATOM_DECL(type); \
+ GLOBAL_ATOM_DECL(udp); \
+ GLOBAL_ATOM_DECL(unblock_source); \
+ GLOBAL_ATOM_DECL(undefined); \
+ GLOBAL_ATOM_DECL(unicast_hops); \
+ GLOBAL_ATOM_DECL(unknown); \
+ GLOBAL_ATOM_DECL(usec); \
+ GLOBAL_ATOM_DECL(user_timeout); \
+ GLOBAL_ATOM_DECL(use_ext_recvinfo); \
+ GLOBAL_ATOM_DECL(use_min_mtu); \
+ GLOBAL_ATOM_DECL(v6only);
+
+
+/* *** Global error reason atoms *** */
+#define GLOBAL_ERROR_REASON_ATOMS \
+ GLOBAL_ATOM_DECL(eagain); \
+ GLOBAL_ATOM_DECL(eafnosupport); \
+ GLOBAL_ATOM_DECL(einval);
+
+
+#define GLOBAL_ATOM_DECL(A) ERL_NIF_TERM esock_atom_##A
+GLOBAL_ATOMS
+GLOBAL_ERROR_REASON_ATOMS
+#undef GLOBAL_ATOM_DECL
+ERL_NIF_TERM esock_atom_socket_tag; // This has a "special" name ('$socket')
+
+/* *** Local atoms *** */
+#define LOCAL_ATOMS \
+ LOCAL_ATOM_DECL(adaptation_layer); \
+ LOCAL_ATOM_DECL(address); \
+ LOCAL_ATOM_DECL(association); \
+ LOCAL_ATOM_DECL(assoc_id); \
+ LOCAL_ATOM_DECL(authentication); \
+ LOCAL_ATOM_DECL(bool); \
+ LOCAL_ATOM_DECL(close); \
+ LOCAL_ATOM_DECL(closed); \
+ LOCAL_ATOM_DECL(closing); \
+ LOCAL_ATOM_DECL(cookie_life); \
+ LOCAL_ATOM_DECL(data_in); \
+ LOCAL_ATOM_DECL(do); \
+ LOCAL_ATOM_DECL(dont); \
+ LOCAL_ATOM_DECL(exclude); \
+ LOCAL_ATOM_DECL(false); \
+ LOCAL_ATOM_DECL(global_counters); \
+ LOCAL_ATOM_DECL(in4_sockaddr); \
+ LOCAL_ATOM_DECL(in6_sockaddr); \
+ LOCAL_ATOM_DECL(include); \
+ LOCAL_ATOM_DECL(initial); \
+ LOCAL_ATOM_DECL(int); \
+ LOCAL_ATOM_DECL(interface); \
+ LOCAL_ATOM_DECL(iow); \
+ LOCAL_ATOM_DECL(local_rwnd); \
+ LOCAL_ATOM_DECL(max); \
+ LOCAL_ATOM_DECL(max_attempts); \
+ LOCAL_ATOM_DECL(max_init_timeo); \
+ LOCAL_ATOM_DECL(max_instreams); \
+ LOCAL_ATOM_DECL(max_rxt); \
+ LOCAL_ATOM_DECL(min); \
+ LOCAL_ATOM_DECL(mode); \
+ LOCAL_ATOM_DECL(multiaddr); \
+ LOCAL_ATOM_DECL(null); \
+ LOCAL_ATOM_DECL(num_dinet); \
+ LOCAL_ATOM_DECL(num_dinet6); \
+ LOCAL_ATOM_DECL(num_dlocal); \
+ LOCAL_ATOM_DECL(num_outstreams); \
+ LOCAL_ATOM_DECL(num_peer_dests); \
+ LOCAL_ATOM_DECL(num_pip); \
+ LOCAL_ATOM_DECL(num_psctp); \
+ LOCAL_ATOM_DECL(num_ptcp); \
+ LOCAL_ATOM_DECL(num_pudp); \
+ LOCAL_ATOM_DECL(num_sockets); \
+ LOCAL_ATOM_DECL(num_tdgrams); \
+ LOCAL_ATOM_DECL(num_tseqpkgs); \
+ LOCAL_ATOM_DECL(num_tstreams); \
+ LOCAL_ATOM_DECL(partial_delivery); \
+ LOCAL_ATOM_DECL(peer_error); \
+ LOCAL_ATOM_DECL(peer_rwnd); \
+ LOCAL_ATOM_DECL(probe); \
+ LOCAL_ATOM_DECL(select); \
+ LOCAL_ATOM_DECL(sender_dry); \
+ LOCAL_ATOM_DECL(send_failure); \
+ LOCAL_ATOM_DECL(shutdown); \
+ LOCAL_ATOM_DECL(slist); \
+ LOCAL_ATOM_DECL(sourceaddr); \
+ LOCAL_ATOM_DECL(timeout); \
+ LOCAL_ATOM_DECL(true); \
+ LOCAL_ATOM_DECL(want);
+
+/* Local error reason atoms */
+#define LOCAL_ERROR_REASON_ATOMS \
+ LOCAL_ATOM_DECL(eisconn); \
+ LOCAL_ATOM_DECL(enotclosing); \
+ LOCAL_ATOM_DECL(enotconn); \
+ LOCAL_ATOM_DECL(exalloc); \
+ LOCAL_ATOM_DECL(exbadstate); \
+ LOCAL_ATOM_DECL(exbusy); \
+ LOCAL_ATOM_DECL(exmon); \
+ LOCAL_ATOM_DECL(exself); \
+ LOCAL_ATOM_DECL(exsend);
+
+#define LOCAL_ATOM_DECL(LA) static ERL_NIF_TERM atom_##LA
+LOCAL_ATOMS
+LOCAL_ERROR_REASON_ATOMS
+#undef LOCAL_ATOM_DECL
/* *** Sockets *** */
@@ -2887,7 +2887,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env,
*
* Description:
* This function is intended to answer the question: "Is X supported?"
- * Currently only one key is "supported": options
+ * Currently three keys are "supported": options | sctp | ipv6
* That results in a list of all *known options* (known by us) and if
* the platform supports (OS) it or not.
*
@@ -4928,14 +4928,15 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
return enif_raise_exception(env, MKA(env, "notsup"));
#else
SocketDescriptor* descP;
- ERL_NIF_TERM ref, res;
+ ERL_NIF_TERM sockRef, ref, res;
SGDBG( ("SOCKET", "nif_accept -> entry with argc: %d\r\n", argc) );
/* Extract arguments and perform preliminary validation */
+ sockRef = argv[0];
if ((argc != 2) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
return enif_make_badarg(env);
}
ref = argv[1];
@@ -4948,7 +4949,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
MLOCK(descP->accMtx);
- res = naccept(env, descP, ref);
+ res = naccept(env, descP, sockRef, ref);
MUNLOCK(descP->accMtx);
@@ -4962,6 +4963,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
static
ERL_NIF_TERM naccept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM ref)
{
ERL_NIF_TERM res;
@@ -4975,7 +4977,7 @@ ERL_NIF_TERM naccept(ErlNifEnv* env,
break;
case SOCKET_STATE_ACCEPTING:
- res = naccept_accepting(env, descP, ref);
+ res = naccept_accepting(env, descP, sockRef, ref);
break;
default:
@@ -5112,6 +5114,7 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
static
ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM ref)
{
ErlNifPid caller;
@@ -5128,15 +5131,12 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
"\r\n Current: %T"
"\r\n", caller, descP->currentAcceptor.pid) );
-
-
-
- if (compare_pids(env, &descP->currentAcceptor.pid, &caller)) {
+ if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) {
SSDBG( descP,
("SOCKET", "naccept_accepting -> current acceptor\r\n") );
- res = naccept_accepting_current(env, descP, ref);
+ res = naccept_accepting_current(env, descP, sockRef, ref);
} else {
@@ -5161,7 +5161,8 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
static
ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
SocketDescriptor* descP,
- ERL_NIF_TERM ref)
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef)
{
SocketAddress remote;
unsigned int n;
@@ -5182,13 +5183,15 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
"naccept_accepting_current -> accept failed: %d\r\n",
save_errno) );
- res = naccept_accepting_current_error(env, descP, ref, save_errno);
+ res = naccept_accepting_current_error(env, descP, sockRef,
+ accRef, save_errno);
} else {
SSDBG( descP, ("SOCKET", "naccept_accepting_current -> accepted\r\n") );
- res = naccept_accepting_current_accept(env, descP, accSock, &remote);
+ res = naccept_accepting_current_accept(env, descP, sockRef,
+ accSock, &remote);
}
@@ -5203,10 +5206,10 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
static
ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
SOCKET accSock,
SocketAddress* remote)
{
- int sres;
ERL_NIF_TERM res;
if (naccept_accepted(env, descP, accSock,
@@ -5220,33 +5223,21 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
*
*/
- if (acceptor_pop(env, descP,
- &descP->currentAcceptor.pid,
- &descP->currentAcceptor.mon,
- &descP->currentAcceptor.ref)) {
-
- /* There was another one */
+ if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
("SOCKET",
- "naccept_accepting_current_accept -> new (active) acceptor: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentAcceptor.pid,
- descP->currentAcceptor.ref) );
+ "naccept_accepting_current_accept -> "
+ "no more writers\r\n") );
- if ((sres = esock_select_read(env, descP->sock, descP,
- &descP->currentAcceptor.pid,
- descP->currentAcceptor.ref)) < 0) {
- esock_warning_msg("Failed select (%d) for new acceptor "
- "after current (%T) died\r\n",
- sres, descP->currentAcceptor.pid);
- }
- } else {
- descP->currentAcceptorP = NULL;
- descP->state = SOCKET_STATE_LISTENING;
+ descP->state = SOCKET_STATE_LISTENING;
+
+ descP->currentAcceptorP = NULL;
+ descP->currentAcceptor.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ esock_monitor_init(&descP->currentAcceptor.mon);
}
+
}
return res;
@@ -5262,10 +5253,12 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
static
ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
SocketDescriptor* descP,
- ERL_NIF_TERM ref,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
int save_errno)
{
- ERL_NIF_TERM res;
+ SocketRequestor req;
+ ERL_NIF_TERM res, reason;
if (save_errno == ERRNO_BLOCK) {
@@ -5275,14 +5268,27 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "naccept_accepting_current_error -> would block: try again\r\n") );
+ "naccept_accepting_current_error -> "
+ "would block: try again\r\n") );
- res = naccept_busy_retry(env, descP, ref, &descP->currentAcceptor.pid,
+ res = naccept_busy_retry(env, descP, opRef, &descP->currentAcceptor.pid,
/* No state change */
descP->state);
} else {
- res = esock_make_error_errno(env, save_errno);
+
+ reason = MKA(env, erl_errno_id(save_errno));
+ res = esock_make_error(env, reason);
+
+ while (acceptor_pop(env, descP, &req)) {
+ SSDBG( descP,
+ ("SOCKET", "naccept_accepting_current_error -> abort %T\r\n",
+ req.pid) );
+ esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid);
+ DEMONP("naccept_accepting_current_error -> pop'ed writer",
+ env, descP, &req.mon);
+ }
+
}
return res;
@@ -7002,7 +7008,7 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
if (enif_self(env, &caller) == NULL)
return esock_make_error(env, atom_exself);
- if (!compare_pids(env, &descP->ctrlPid, &caller)) {
+ if (COMPARE_PIDS(&descP->ctrlPid, &caller) != 0) {
SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> not owner (%T)\r\n",
descP->ctrlPid) );
return esock_make_error(env, esock_atom_not_owner);
@@ -9491,7 +9497,6 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
int res;
size_t sz;
unsigned int tmp;
- Sint32 tmpAssocId;
SSDBG( descP,
("SOCKET", "nsetopt_lvl_sctp_associnfo -> entry with"
@@ -9532,10 +9537,29 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
/* On some platforms the assoc id is typed as an unsigned integer (uint32)
* So, to avoid warnings there, we always make an explicit cast...
+ * Also, size of types matter, so adjust for that...
*/
- if (!GET_INT(env, eAssocId, &tmpAssocId))
- return esock_make_error(env, esock_atom_einval);
- assocParams.sasoc_assoc_id = (typeof(assocParams.sasoc_assoc_id)) tmpAssocId;
+
+#if (SIZEOF_INT == 4)
+ {
+ int tmpAssocId;
+ if (!GET_INT(env, eAssocId, &tmpAssocId))
+ return esock_make_error(env, esock_atom_einval);
+ assocParams.sasoc_assoc_id =
+ (typeof(assocParams.sasoc_assoc_id)) tmpAssocId;
+ }
+#elif (SIZEOF_LONG == 4)
+ {
+ long tmpAssocId;
+ if (!GET_LONG(env, eAssocId, &tmpAssocId))
+ return esock_make_error(env, esock_atom_einval);
+ assocParams.sasoc_assoc_id =
+ (typeof(assocParams.sasoc_assoc_id)) tmpAssocId;
+ }
+#else
+ SIZE CHECK FOR ASSOC ID FAILED
+#endif
+
/*
* We should really make sure this is ok in erlang (to ensure that
@@ -9620,7 +9644,10 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
ERL_NIF_TERM result;
ERL_NIF_TERM eDataIn, eAssoc, eAddr, eSndFailure;
ERL_NIF_TERM ePeerError, eShutdown, ePartialDelivery;
- ERL_NIF_TERM eAdaptLayer, eAuth;
+ ERL_NIF_TERM eAdaptLayer;
+#if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_AUTHENTICATION_EVENT)
+ ERL_NIF_TERM eAuth;
+#endif
#if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SENDER_DRY_EVENT)
ERL_NIF_TERM eSndDry;
#endif
@@ -9841,7 +9868,6 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
struct sctp_rtoinfo rtoInfo;
int res;
size_t sz;
- Sint32 tmpAssocId;
SSDBG( descP,
("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> entry with"
@@ -9876,10 +9902,31 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
/* On some platforms the assoc id is typed as an unsigned integer (uint32)
* So, to avoid warnings there, we always make an explicit cast...
+ * Also, size of types matter, so adjust for that...
*/
+
+#if (SIZEOF_INT == 4)
+ {
+ int tmpAssocId;
+ if (!GET_INT(env, eAssocId, &tmpAssocId))
+ return esock_make_error(env, esock_atom_einval);
+ rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId;
+ }
+#elif (SIZEOF_LONG == 4)
+ {
+ long tmpAssocId;
+ if (!GET_LONG(env, eAssocId, &tmpAssocId))
+ return esock_make_error(env, esock_atom_einval);
+ rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId;
+ }
+#else
+ SIZE CHECK FOR ASSOC ID FAILED
+#endif
+ /*
if (!GET_INT(env, eAssocId, &tmpAssocId))
return esock_make_error(env, esock_atom_einval);
rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId;
+ */
if (!GET_UINT(env, eInitial, &rtoInfo.srto_initial))
return esock_make_error(env, esock_atom_einval);
@@ -9985,6 +10032,7 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
/* nsetopt_str_opt - set an option that has an string value
*/
+#if defined(USE_SETOPT_STR_OPT)
static
ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -10013,6 +10061,7 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
return result;
}
+#endif
/* nsetopt_timeval_opt - set an option that has an (timeval) bool value
@@ -10503,7 +10552,7 @@ static
ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val = descP->domain;
switch (val) {
@@ -10524,10 +10573,8 @@ ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
#endif
default:
- result = esock_make_error(env,
- MKT2(env,
- esock_atom_unknown,
- MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
@@ -10541,7 +10588,7 @@ static
ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val = descP->type;
switch (val) {
@@ -10567,8 +10614,8 @@ ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
break;
default:
- result = esock_make_error(env,
- MKT2(env, esock_atom_unknown, MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
@@ -10582,7 +10629,7 @@ static
ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val = descP->protocol;
switch (val) {
@@ -10605,8 +10652,8 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
#endif
default:
- result = esock_make_error(env,
- MKT2(env, esock_atom_unknown, MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
@@ -11021,7 +11068,7 @@ static
ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
@@ -11050,10 +11097,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
#endif
default:
- result = esock_make_error(env,
- MKT2(env,
- esock_atom_unknown,
- MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
}
@@ -11148,7 +11193,7 @@ static
ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
@@ -11179,8 +11224,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
#endif
default:
- result = esock_make_error(env,
- MKT2(env, esock_atom_unknown, MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
}
@@ -11285,7 +11330,7 @@ static
ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
SocketDescriptor* descP)
{
- ERL_NIF_TERM result;
+ ERL_NIF_TERM result, reason;
int val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
@@ -11314,8 +11359,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
result = esock_make_ok2(env, esock_atom_rdm);
break;
default:
- result = esock_make_error(env,
- MKT2(env, esock_atom_unknown, MKI(env, val)));
+ reason = MKT2(env, esock_atom_unknown, MKI(env, val));
+ result = esock_make_error(env, reason);
break;
}
}
@@ -11485,7 +11530,8 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
#endif
default:
- SSDBG( descP, ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) );
+ SSDBG( descP,
+ ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) );
result = esock_make_error(env, esock_atom_einval);
break;
}
@@ -12910,6 +12956,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
* The actual size of the (read) value will be communicated
* in the optSz variable.
*/
+#if defined(USE_GETOPT_STR_OPT)
static
ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -12948,6 +12995,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
return result;
}
+#endif // if defined(USE_GETOPT_STR_OPT)
#endif // if !defined(__WIN32__)
@@ -13120,14 +13168,15 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
return enif_raise_exception(env, MKA(env, "notsup"));
#else
SocketDescriptor* descP;
- ERL_NIF_TERM op, opRef, result;
+ ERL_NIF_TERM op, sockRef, opRef, result;
SGDBG( ("SOCKET", "nif_cancel -> entry with argc: %d\r\n", argc) );
/* Extract arguments and perform preliminary validation */
+ sockRef = argv[0];
if ((argc != 3) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
return enif_make_badarg(env);
}
op = argv[1];
@@ -13142,7 +13191,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
"\r\n opRef: %T"
"\r\n", descP->sock, op, opRef) );
- result = ncancel(env, descP, op, opRef);
+ result = ncancel(env, descP, op, sockRef, opRef);
SSDBG( descP,
("SOCKET", "nif_cancel -> done with result: "
@@ -13159,6 +13208,7 @@ static
ERL_NIF_TERM ncancel(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM op,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef)
{
/* <KOLLA>
@@ -13172,19 +13222,19 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env,
if (COMPARE(op, esock_atom_connect) == 0) {
return ncancel_connect(env, descP, opRef);
} else if (COMPARE(op, esock_atom_accept) == 0) {
- return ncancel_accept(env, descP, opRef);
+ return ncancel_accept(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_send) == 0) {
- return ncancel_send(env, descP, opRef);
+ return ncancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_sendto) == 0) {
- return ncancel_send(env, descP, opRef);
+ return ncancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_sendmsg) == 0) {
- return ncancel_send(env, descP, opRef);
+ return ncancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recv) == 0) {
- return ncancel_recv(env, descP, opRef);
+ return ncancel_recv(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recvfrom) == 0) {
- return ncancel_recv(env, descP, opRef);
+ return ncancel_recv(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recvmsg) == 0) {
- return ncancel_recv(env, descP, opRef);
+ return ncancel_recv(env, descP, sockRef, opRef);
} else {
return esock_make_error(env, esock_atom_einval);
}
@@ -13218,6 +13268,7 @@ ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
static
ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13233,7 +13284,7 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
if (descP->currentAcceptorP != NULL) {
if (COMPARE(opRef, descP->currentAcceptor.ref) == 0) {
- res = ncancel_accept_current(env, descP);
+ res = ncancel_accept_current(env, descP, sockRef);
} else {
res = ncancel_accept_waiting(env, descP, opRef);
}
@@ -13259,9 +13310,9 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
*/
static
ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- SocketDescriptor* descP)
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
- int sres;
ERL_NIF_TERM res;
SSDBG( descP, ("SOCKET", "ncancel_accept_current -> entry\r\n") );
@@ -13270,36 +13321,22 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
env, descP, &descP->currentAcceptor.mon);
res = ncancel_read_select(env, descP, descP->currentAcceptor.ref);
- SSDBG( descP, ("SOCKET", "ncancel_accept_current -> cancel res: %T\r\n", res) );
+ SSDBG( descP, ("SOCKET",
+ "ncancel_accept_current -> cancel res: %T\r\n", res) );
- if (acceptor_pop(env, descP,
- &descP->currentAcceptor.pid,
- &descP->currentAcceptor.mon,
- &descP->currentAcceptor.ref)) {
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "ncancel_accept_current -> new (active) acceptor: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentAcceptor.pid,
- descP->currentAcceptor.ref) );
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- &descP->currentAcceptor.pid,
- descP->currentAcceptor.ref)) < 0) {
- return esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- }
- } else {
- SSDBG( descP, ("SOCKET", "ncancel_accept_current -> no more acceptors\r\n") );
- descP->currentAcceptorP = NULL;
- descP->state = SOCKET_STATE_LISTENING;
+ if (!activate_next_acceptor(env, descP, sockRef)) {
+
+ SSDBG( descP,
+ ("SOCKET", "ncancel_accept_current -> no more writers\r\n") );
+
+ descP->state = SOCKET_STATE_LISTENING;
+
+ descP->currentAcceptorP = NULL;
+ descP->currentAcceptor.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ esock_monitor_init(&descP->currentAcceptor.mon);
}
-
+
SSDBG( descP, ("SOCKET", "ncancel_accept_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -13341,6 +13378,7 @@ ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
static
ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13356,7 +13394,7 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
if (descP->currentWriterP != NULL) {
if (COMPARE(opRef, descP->currentWriter.ref) == 0) {
- res = ncancel_send_current(env, descP);
+ res = ncancel_send_current(env, descP, sockRef);
} else {
res = ncancel_send_waiting(env, descP, opRef);
}
@@ -13383,46 +13421,29 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
*/
static
ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- SocketDescriptor* descP)
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
- int sres;
ERL_NIF_TERM res;
SSDBG( descP, ("SOCKET", "ncancel_send_current -> entry\r\n") );
- DEMONP("ncancel_recv_current -> current writer",
+ DEMONP("ncancel_send_current -> current writer",
env, descP, &descP->currentWriter.mon);
res = ncancel_write_select(env, descP, descP->currentWriter.ref);
- SSDBG( descP, ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) );
+ SSDBG( descP,
+ ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) );
- if (writer_pop(env, descP,
- &descP->currentWriter.pid,
- &descP->currentWriter.mon,
- &descP->currentWriter.ref)) {
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "ncancel_send_current -> new (active) writer: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentWriter.pid,
- descP->currentWriter.ref) );
-
- if ((sres = esock_select_write(env, descP->sock, descP,
- &descP->currentWriter.pid,
- descP->currentWriter.ref)) < 0) {
- return esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- }
- } else {
- SSDBG( descP, ("SOCKET", "ncancel_send_current -> no more writers\r\n") );
- descP->currentWriterP = NULL;
+ if (!activate_next_writer(env, descP, sockRef)) {
+ SSDBG( descP,
+ ("SOCKET", "ncancel_send_current -> no more writers\r\n") );
+ descP->currentWriterP = NULL;
+ descP->currentWriter.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentWriter.pid);
+ esock_monitor_init(&descP->currentWriter.mon);
}
-
+
SSDBG( descP, ("SOCKET", "ncancel_send_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -13464,6 +13485,7 @@ ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
static
ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13479,7 +13501,7 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
if (descP->currentReaderP != NULL) {
if (COMPARE(opRef, descP->currentReader.ref) == 0) {
- res = ncancel_recv_current(env, descP);
+ res = ncancel_recv_current(env, descP, sockRef);
} else {
res = ncancel_recv_waiting(env, descP, opRef);
}
@@ -13505,9 +13527,9 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
*/
static
ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- SocketDescriptor* descP)
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
- int sres;
ERL_NIF_TERM res;
SSDBG( descP, ("SOCKET", "ncancel_recv_current -> entry\r\n") );
@@ -13516,35 +13538,18 @@ ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
env, descP, &descP->currentReader.mon);
res = ncancel_read_select(env, descP, descP->currentReader.ref);
- SSDBG( descP, ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) );
+ SSDBG( descP,
+ ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) );
- if (reader_pop(env, descP,
- &descP->currentReader.pid,
- &descP->currentReader.mon,
- &descP->currentReader.ref)) {
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "ncancel_recv_current -> new (active) reader: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentReader.pid,
- descP->currentReader.ref) );
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- &descP->currentReader.pid,
- descP->currentReader.ref)) < 0) {
- return esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- }
- } else {
- SSDBG( descP, ("SOCKET", "ncancel_recv_current -> no more readers\r\n") );
- descP->currentReaderP = NULL;
+ if (!activate_next_reader(env, descP, sockRef)) {
+ SSDBG( descP,
+ ("SOCKET", "ncancel_recv_current -> no more readers\r\n") );
+ descP->currentReaderP = NULL;
+ descP->currentReader.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentReader.pid);
+ esock_monitor_init(&descP->currentReader.mon);
}
-
+
SSDBG( descP, ("SOCKET", "ncancel_recv_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -13653,7 +13658,7 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env,
return FALSE;
}
- if (!compare_pids(env, &descP->currentWriter.pid, &caller)) {
+ if (COMPARE_PIDS(&descP->currentWriter.pid, &caller) != 0) {
/* Not the "current writer", so (maybe) push onto queue */
SSDBG( descP,
@@ -13727,30 +13732,11 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env,
/* Ok, this write is done maybe activate the next (if any) */
- if (writer_pop(env, descP,
- &descP->currentWriter.pid,
- &descP->currentWriter.mon,
- &descP->currentWriter.ref)) {
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "send_check_result -> new (active) writer: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentWriter.pid,
- descP->currentWriter.ref) );
-
- if ((sres = esock_select_write(env, descP->sock, descP,
- &descP->currentWriter.pid,
- descP->currentWriter.ref)) < 0) {
- return esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- }
- } else {
- descP->currentWriterP = NULL;
+ if (!activate_next_writer(env, descP, sockRef)) {
+ descP->currentWriterP = NULL;
+ descP->currentWriter.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentWriter.pid);
+ esock_monitor_init(&descP->currentWriter.mon);
}
return esock_atom_ok;
@@ -13760,10 +13746,8 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env,
/* Some kind of send failure - check what kind */
if ((saveErrno != EAGAIN) && (saveErrno != EINTR)) {
- ErlNifPid pid;
- // ErlNifMonitor mon;
- ESockMonitor mon;
- ERL_NIF_TERM ref, res;
+ SocketRequestor req;
+ ERL_NIF_TERM res, reason;
/*
* An actual failure - we (and everyone waiting) give up
@@ -13772,20 +13756,25 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env,
cnt_inc(&descP->writeFails, 1);
SSDBG( descP,
- ("SOCKET", "send_check_result -> error: %d\r\n", saveErrno) );
+ ("SOCKET",
+ "send_check_result -> error: %d\r\n", saveErrno) );
- res = esock_make_error_errno(env, saveErrno);
+ reason = MKA(env, erl_errno_id(saveErrno));
+ res = esock_make_error(env, reason);
if (descP->currentWriterP != NULL) {
+
DEMONP("send_check_result -> current writer",
env, descP, &descP->currentWriter.mon);
- while (writer_pop(env, descP, &pid, &mon, &ref)) {
+ while (writer_pop(env, descP, &req)) {
SSDBG( descP,
- ("SOCKET", "send_check_result -> abort %T\r\n", pid) );
- esock_send_abort_msg(env, sockRef, ref, res, &pid);
+ ("SOCKET", "send_check_result -> abort %T\r\n",
+ req.pid) );
+ esock_send_abort_msg(env, sockRef, req.ref,
+ reason, &req.pid);
DEMONP("send_check_result -> pop'ed writer",
- env, descP, &mon);
+ env, descP, &req.mon);
}
}
@@ -13877,7 +13866,7 @@ BOOLEAN_T recv_check_reader(ErlNifEnv* env,
return FALSE;
}
- if (!compare_pids(env, &descP->currentReader.pid, &caller)) {
+ if (COMPARE_PIDS(&descP->currentReader.pid, &caller) != 0) {
ERL_NIF_TERM tmp;
/* Not the "current reader", so (maybe) push onto queue */
@@ -13950,9 +13939,9 @@ char* recv_init_current_reader(ErlNifEnv* env,
static
ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP)
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
- int sres;
ERL_NIF_TERM res = esock_atom_ok;
if (descP->currentReaderP != NULL) {
@@ -13960,32 +13949,18 @@ ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
DEMONP("recv_update_current_reader -> current reader",
env, descP, &descP->currentReader.mon);
- if (reader_pop(env, descP,
- &descP->currentReader.pid,
- &descP->currentReader.mon,
- &descP->currentReader.ref)) {
-
- /* There was another one */
-
+ if (!activate_next_reader(env, descP, sockRef)) {
+
SSDBG( descP,
- ("SOCKET", "recv_update_current_reader -> new (active) reader: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentReader.pid,
- descP->currentReader.ref) );
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- &descP->currentReader.pid,
- descP->currentReader.ref)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- }
- } else {
- descP->currentReaderP = NULL;
+ ("SOCKET",
+ "recv_update_current_reader -> no more readers\r\n") );
+
+ descP->currentReaderP = NULL;
+ descP->currentReader.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentReader.pid);
+ esock_monitor_init(&descP->currentReader.mon);
}
+
}
return res;
@@ -14006,21 +13981,20 @@ void recv_error_current_reader(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM reason)
{
+ SocketRequestor req;
+
if (descP->currentReaderP != NULL) {
- ErlNifPid pid;
- // ErlNifMonitor mon;
- ESockMonitor mon;
- ERL_NIF_TERM ref;
DEMONP("recv_error_current_reader -> current reader",
env, descP, &descP->currentReader.mon);
- while (reader_pop(env, descP, &pid, &mon, &ref)) {
+ while (reader_pop(env, descP, &req)) {
SSDBG( descP,
- ("SOCKET", "recv_error_current_reader -> abort %T\r\n", pid) );
- esock_send_abort_msg(env, sockRef, ref, reason, &pid);
+ ("SOCKET", "recv_error_current_reader -> abort %T\r\n",
+ req.pid) );
+ esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid);
DEMONP("recv_error_current_reader -> pop'ed reader",
- env, descP, &mon);
+ env, descP, &req.mon);
}
}
}
@@ -14137,7 +14111,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
cnt_inc(&descP->readPkgCnt, 1);
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
/* This transfers "ownership" of the *allocated* binary to an
* erlang term (no need for an explicit free).
@@ -14182,7 +14156,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
"recv_check_result -> [%d] "
"we got exactly what we could fit\r\n", toRead) );
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
/* This transfers "ownership" of the *allocated* binary to an
* erlang term (no need for an explicit free).
@@ -14294,7 +14268,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
cnt_inc(&descP->readPkgCnt, 1);
cnt_inc(&descP->readByteCnt, read);
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
/* This transfers "ownership" of the *allocated* binary to an
* erlang term (no need for an explicit free).
@@ -14479,7 +14453,7 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
data = MKSBIN(env, data, 0, read);
}
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
return esock_make_ok2(env, MKT2(env, eSockAddr, data));
@@ -14644,7 +14618,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
"recvmsg_check_result -> "
"(msghdr) encode failed: %s\r\n", xres) );
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
@@ -14656,7 +14630,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
"recvmsg_check_result -> "
"(msghdr) encode ok: %T\r\n", eMsgHdr) );
- recv_update_current_reader(env, descP);
+ recv_update_current_reader(env, descP, sockRef);
return esock_make_ok2(env, eMsgHdr);
}
@@ -16299,6 +16273,7 @@ ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val)
/* *** alloc_descriptor ***
+ *
* Allocate and perform basic initialization of a socket descriptor.
*
*/
@@ -16370,14 +16345,16 @@ SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
-/* decrement counters for when a socket is closed */
+/* Decrement counters for when a socket is closed
+ */
static
void dec_socket(int domain, int type, int protocol)
{
MLOCK(data.cntMtx);
cnt_dec(&data.numSockets, 1);
-
+
+ /* *** Domain counter *** */
if (domain == AF_INET)
cnt_dec(&data.numDomainInet, 1);
#if defined(HAVE_IN6) && defined(AF_INET6)
@@ -16389,6 +16366,7 @@ void dec_socket(int domain, int type, int protocol)
cnt_dec(&data.numDomainInet6, 1);
#endif
+ /* *** Type counter *** */
if (type == SOCK_STREAM)
cnt_dec(&data.numTypeStreams, 1);
else if (type == SOCK_DGRAM)
@@ -16398,6 +16376,7 @@ void dec_socket(int domain, int type, int protocol)
cnt_dec(&data.numTypeSeqPkgs, 1);
#endif
+ /* *** Protocol counter *** */
if (protocol == IPPROTO_IP)
cnt_dec(&data.numProtoIP, 1);
else if (protocol == IPPROTO_TCP)
@@ -16413,7 +16392,8 @@ void dec_socket(int domain, int type, int protocol)
}
-/* increment counters for when a socket is opened */
+/* Increment counters for when a socket is opened
+ */
static
void inc_socket(int domain, int type, int protocol)
{
@@ -16421,6 +16401,7 @@ void inc_socket(int domain, int type, int protocol)
cnt_inc(&data.numSockets, 1);
+ /* *** Domain counter *** */
if (domain == AF_INET)
cnt_inc(&data.numDomainInet, 1);
#if defined(HAVE_IN6) && defined(AF_INET6)
@@ -16432,6 +16413,7 @@ void inc_socket(int domain, int type, int protocol)
cnt_inc(&data.numDomainInet6, 1);
#endif
+ /* *** Type counter *** */
if (type == SOCK_STREAM)
cnt_inc(&data.numTypeStreams, 1);
else if (type == SOCK_DGRAM)
@@ -16441,6 +16423,7 @@ void inc_socket(int domain, int type, int protocol)
cnt_inc(&data.numTypeSeqPkgs, 1);
#endif
+ /* *** Protocol counter *** */
if (protocol == IPPROTO_IP)
cnt_inc(&data.numProtoIP, 1);
else if (protocol == IPPROTO_TCP)
@@ -16456,20 +16439,6 @@ void inc_socket(int domain, int type, int protocol)
}
-
-/* compare_pids - Test if two pids are equal
- *
- */
-static
-int compare_pids(ErlNifEnv* env,
- const ErlNifPid* pid1,
- const ErlNifPid* pid2)
-{
- ERL_NIF_TERM p1 = enif_make_pid(env, pid1);
- ERL_NIF_TERM p2 = enif_make_pid(env, pid2);
-
- return enif_is_identical(p1, p2);
-}
#endif // if !defined(__WIN32__)
@@ -17070,280 +17039,261 @@ int esock_select_cancel(ErlNifEnv* env,
/* ----------------------------------------------------------------------
- * R e q u e s t Q u e u e F u n c t i o n s
+ * A c t i v a t e N e x t ( o p e r a t o r ) F u n c t i o n s
* ----------------------------------------------------------------------
*/
-/* *** acceptor search for pid ***
+/* *** activate_next_acceptor ***
+ * *** activate_next_writer ***
+ * *** activate_next_reader ***
*
- * Search for a pid in the acceptor queue.
- */
-#if !defined(__WIN32__)
-static
-BOOLEAN_T acceptor_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid)
-{
- return qsearch4pid(env, &descP->acceptorsQ, pid);
-}
+ * This functions pops the writer queue and then selects until it
+ * manages to successfully activate a writer or the queue is empty.
+ */
+
+#define ACTIVATE_NEXT_FUNCS \
+ ACTIVATE_NEXT_FUNC_DECL(acceptor, currentAcceptor, acceptorsQ) \
+ ACTIVATE_NEXT_FUNC_DECL(writer, currentWriter, writersQ) \
+ ACTIVATE_NEXT_FUNC_DECL(reader, currentReader, readersQ)
+
+#define ACTIVATE_NEXT_FUNC_DECL(F, R, Q) \
+ static \
+ BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ERL_NIF_TERM sockRef) \
+ { \
+ return activate_next(env, descP, \
+ &descP->R, &descP->Q, \
+ sockRef); \
+ }
+ACTIVATE_NEXT_FUNCS
+#undef ACTIVATE_NEXT_FUNC_DECL
-/* *** acceptor push ***
+/* *** activate_next ***
*
- * Push an acceptor onto the acceptor queue.
- * This happens when we already have atleast one current acceptor.
+ * This functions pops the requestor queue and then selects until it
+ * manages to successfully activate a new requestor or the queue is empty.
+ * Return value indicates if a new requestor was activated or not.
*/
+
static
-ERL_NIF_TERM acceptor_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref)
+BOOLEAN_T activate_next(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ SocketRequestor* reqP,
+ SocketRequestQueue* q,
+ ERL_NIF_TERM sockRef)
{
- SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement));
- SocketRequestor* reqP = &e->data;
+ BOOLEAN_T popped, activated;
+ int sres;
- reqP->pid = pid;
- reqP->ref = enif_make_copy(descP->env, ref);
-
- if (MONP("acceptor_push -> acceptor request",
- env, descP, &pid, &reqP->mon) != 0) {
- FREE(reqP);
- return esock_make_error(env, atom_exmon);
- }
-
- qpush(&descP->acceptorsQ, e);
-
- // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN
- return esock_make_error(env, esock_atom_eagain);
-}
+ popped = FALSE;
+ do {
+ if (requestor_pop(q, reqP)) {
-/* *** acceptor pop ***
- *
- * Pop an acceptor from the acceptor queue.
- */
-static
-BOOLEAN_T acceptor_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref)
-{
- SocketRequestQueueElement* e = qpop(&descP->acceptorsQ);
+ /* There was another one */
+
+ SSDBG( descP,
+ ("SOCKET", "activate_next -> new (active) requestor: "
+ "\r\n pid: %T"
+ "\r\n ref: %T"
+ "\r\n", reqP->pid, reqP->ref) );
+
+ if ((sres = esock_select_read(env, descP->sock, descP,
+ &reqP->pid, reqP->ref)) < 0) {
+ /* We need to inform this process, reqP->pid, that we
+ * failed to select, so we don't leave it hanging.
+ * => send abort
+ */
- if (e != NULL) {
- *pid = e->data.pid;
- *mon = e->data.mon;
- *ref = e->data.ref;
- FREE(e);
- return TRUE;
- } else {
- /* (acceptors) Queue was empty */
- // *pid = NULL; we have no null value for pids
- // *mon = NULL; we have no null value for monitors
- *ref = esock_atom_undefined; // Just in case
- return FALSE;
- }
-
-}
+ esock_send_abort_msg(env, sockRef, reqP->ref, sres, &reqP->pid);
+
+ } else {
+ /* Success: New requestor selected */
+ popped = TRUE;
+ activated = FALSE;
-/* *** acceptor unqueue ***
- *
- * Remove an acceptor from the acceptor queue.
- */
-static
-BOOLEAN_T acceptor_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid)
-{
- return qunqueue(env, descP, "qunqueue -> waiting acceptor",
- &descP->acceptorsQ, pid);
-}
+ }
+ } else {
+ SSDBG( descP,
+ ("SOCKET", "send_activate_next -> no more requestors\r\n") );
-/* *** writer search for pid ***
- *
- * Search for a pid in the writer queue.
- */
-static
-BOOLEAN_T writer_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid)
-{
- return qsearch4pid(env, &descP->writersQ, pid);
+ popped = TRUE;
+ activated = FALSE;
+ }
+
+ } while (!popped);
+
+ SSDBG( descP,
+ ("SOCKET", "activate_next -> "
+ "done with %s\r\n", B2S(activated)) );
+
+ return activated;
}
-/* *** writer push ***
+/* ----------------------------------------------------------------------
+ * R e q u e s t o r Q u e u e F u n c t i o n s
+ * ----------------------------------------------------------------------
*
- * Push an writer onto the writer queue.
- * This happens when we already have atleast one current writer.
+ * Since each of these functions (search4pid, push, pop and unqueue
+ * are virtually identical for acceptors, writers and readers,
+ * we make use of set of declaration macros.
*/
-static
-ERL_NIF_TERM writer_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref)
-{
- SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement));
- SocketRequestor* reqP = &e->data;
-
- reqP->pid = pid;
- reqP->ref = enif_make_copy(descP->env, ref);
-
- if (MONP("writer_push -> writer request",
- env, descP, &pid, &reqP->mon) != 0) {
- FREE(reqP);
- return esock_make_error(env, atom_exmon);
- }
-
- qpush(&descP->writersQ, e);
-
- // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN
- return esock_make_error(env, esock_atom_eagain);
-}
+#if !defined(__WIN32__)
-/* *** writer pop ***
+/* *** acceptor_search4pid ***
+ * *** writer_search4pid ***
+ * *** reader_search4pid ***
+ *
+ * Search for a pid in the requestor (acceptor, writer, or reader) queue.
*
- * Pop an writer from the writer queue.
*/
-static
-BOOLEAN_T writer_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref)
-{
- SocketRequestQueueElement* e = qpop(&descP->writersQ);
- if (e != NULL) {
- *pid = e->data.pid;
- *mon = e->data.mon;
- *ref = e->data.ref; // At this point the ref has already been copied (env)
- FREE(e);
- return TRUE;
- } else {
- /* (writers) Queue was empty */
- // *pid = NULL; we have no null value for pids
- // *mon = NULL; we have no null value for monitors
- *ref = esock_atom_undefined; // Just in case
- return FALSE;
+#define REQ_SEARCH4PID_FUNCS \
+ REQ_SEARCH4PID_FUNC_DECL(acceptor, acceptorsQ) \
+ REQ_SEARCH4PID_FUNC_DECL(writer, writersQ) \
+ REQ_SEARCH4PID_FUNC_DECL(reader, readersQ)
+
+#define REQ_SEARCH4PID_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_search4pid(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ErlNifPid* pid) \
+ { \
+ return qsearch4pid(env, &descP->Q, pid); \
}
-
-}
+REQ_SEARCH4PID_FUNCS
+#undef REQ_SEARCH4PID_FUNC_DECL
+
-/* *** writer unqueue ***
+/* *** acceptor_push ***
+ * *** writer_push ***
+ * *** reader_push ***
+ *
+ * Push a requestor (acceptor, writer, or reader) onto its queue.
+ * This happens when we already have a current request (of its type).
*
- * Remove an writer from the writer queue.
*/
-static
-BOOLEAN_T writer_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid)
-{
- return qunqueue(env, descP, "qunqueue -> waiting writer",
- &descP->writersQ, pid);
-}
+
+#define REQ_PUSH_FUNCS \
+ REQ_PUSH_FUNC_DECL(acceptor, acceptorsQ) \
+ REQ_PUSH_FUNC_DECL(writer, writersQ) \
+ REQ_PUSH_FUNC_DECL(reader, readersQ)
+
+#define REQ_PUSH_FUNC_DECL(F, Q) \
+ static \
+ ERL_NIF_TERM F##_push(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ ErlNifPid pid, \
+ ERL_NIF_TERM ref) \
+ { \
+ SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); \
+ SocketRequestor* reqP = &e->data; \
+ \
+ reqP->pid = pid; \
+ reqP->ref = enif_make_copy(descP->env, ref); \
+ \
+ if (MONP("reader_push -> " #F " request", \
+ env, descP, &pid, &reqP->mon) != 0) { \
+ FREE(reqP); \
+ return esock_make_error(env, atom_exmon); \
+ } \
+ \
+ qpush(&descP->Q, e); \
+ \
+ return esock_make_error(env, esock_atom_eagain); \
+ }
+REQ_PUSH_FUNCS
+#undef REQ_PUSH_FUNC_DECL
-/* *** reader search for pid ***
+/* *** acceptor_pop ***
+ * *** writer_pop ***
+ * *** reader_pop ***
+ *
+ * Pop a requestor (acceptor, writer, or reader) from its queue.
*
- * Search for a pid in the reader queue.
*/
-static
-BOOLEAN_T reader_search4pid(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid)
-{
- return qsearch4pid(env, &descP->readersQ, pid);
-}
+#define REQ_POP_FUNCS \
+ REQ_POP_FUNC_DECL(acceptor, acceptorsQ) \
+ REQ_POP_FUNC_DECL(writer, writersQ) \
+ REQ_POP_FUNC_DECL(reader, readersQ)
+
+#define REQ_POP_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_pop(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ SocketRequestor* reqP) \
+ { \
+ return requestor_pop(&descP->Q, reqP); \
+ }
+REQ_POP_FUNCS
+#undef REQ_POP_FUNC_DECL
-/* *** reader push ***
+
+/* *** acceptor_unqueue ***
+ * *** writer_unqueue ***
+ * *** reader_unqueue ***
+ *
+ * Remove a requestor (acceptor, writer, or reader) from its queue.
*
- * Push an reader onto the raeder queue.
- * This happens when we already have atleast one current reader.
*/
-static
-ERL_NIF_TERM reader_push(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid pid,
- ERL_NIF_TERM ref)
-{
- SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement));
- SocketRequestor* reqP = &e->data;
-
- reqP->pid = pid;
- reqP->ref = enif_make_copy(descP->env, ref);
-
- if (MONP("reader_push -> reader request",
- env, descP, &pid, &reqP->mon) != 0) {
- FREE(reqP);
- return esock_make_error(env, atom_exmon);
+
+#define REQ_UNQUEUE_FUNCS \
+ REQ_UNQUEUE_FUNC_DECL(acceptor, acceptorsQ) \
+ REQ_UNQUEUE_FUNC_DECL(writer, writersQ) \
+ REQ_UNQUEUE_FUNC_DECL(reader, readersQ)
+
+#define REQ_UNQUEUE_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_unqueue(ErlNifEnv* env, \
+ SocketDescriptor* descP, \
+ const ErlNifPid* pid) \
+ { \
+ return qunqueue(env, descP, "qunqueue -> waiting " #F, \
+ &descP->Q, pid); \
}
-
- qpush(&descP->readersQ, e);
-
- // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN
- return esock_make_error(env, esock_atom_eagain);
-}
+REQ_UNQUEUE_FUNCS
+#undef REQ_UNQUEUE_FUNC_DECL
+
-/* *** reader pop ***
+/* *** requestor pop ***
*
- * Pop an writer from the reader queue.
+ * Pop an requestor from its queue.
*/
static
-BOOLEAN_T reader_pop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifPid* pid,
- // ErlNifMonitor* mon,
- ESockMonitor* mon,
- ERL_NIF_TERM* ref)
+BOOLEAN_T requestor_pop(SocketRequestQueue* q,
+ SocketRequestor* reqP)
{
- SocketRequestQueueElement* e = qpop(&descP->readersQ);
+ SocketRequestQueueElement* e = qpop(q);
if (e != NULL) {
- *pid = e->data.pid;
- *mon = e->data.mon;
- *ref = e->data.ref; // At this point the ref has already been copied (env)
+ reqP->pid = e->data.pid;
+ reqP->mon = e->data.mon;
+ reqP->ref = e->data.ref;
FREE(e);
return TRUE;
} else {
- /* (readers) Queue was empty */
- // *pid = NULL; we have no null value for pids
- // *mon = NULL; we have no null value for monitors
- *ref = esock_atom_undefined; // Just in case
+ /* (writers) Queue was empty */
+ enif_set_pid_undefined(&reqP->pid);
+ // *reqP->mon = NULL; we have no null value for monitors
+ reqP->ref = esock_atom_undefined; // Just in case
return FALSE;
}
}
-/* *** reader unqueue ***
- *
- * Remove an reader from the reader queue.
- */
-static
-BOOLEAN_T reader_unqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid)
-{
- return qunqueue(env, descP, "qunqueue -> waiting reader",
- &descP->readersQ, pid);
-}
-
-
-
-
-
static
BOOLEAN_T qsearch4pid(ErlNifEnv* env,
SocketRequestQueue* q,
@@ -17352,7 +17302,7 @@ BOOLEAN_T qsearch4pid(ErlNifEnv* env,
SocketRequestQueueElement* tmp = q->first;
while (tmp != NULL) {
- if (compare_pids(env, &tmp->data.pid, pid))
+ if (COMPARE_PIDS(&tmp->data.pid, pid) == 0)
return TRUE;
else
tmp = tmp->nextP;
@@ -17411,7 +17361,7 @@ BOOLEAN_T qunqueue(ErlNifEnv* env,
/* Check if it was one of the waiting acceptor processes */
while (e != NULL) {
- if (compare_pids(env, &e->data.pid, pid)) {
+ if (COMPARE_PIDS(&e->data.pid, pid) == 0) {
/* We have a match */
@@ -17502,12 +17452,6 @@ void cnt_dec(Uint32* cnt, Uint32 dec)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM my_make_monitor_term(ErlNifEnv* env, const ErlNifMonitor* mon)
-{
- return ((ERL_NIF_TERM)&mon->data) + 2;
-}
-
-static
int esock_monitor(const char* slogan,
ErlNifEnv* env,
SocketDescriptor* descP,
@@ -17660,7 +17604,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
descP->readTries,
descP->readWaits) );
- sockRef = enif_make_resource(env, descP),
+ sockRef = enif_make_resource(env, descP);
descP->state = SOCKET_STATE_CLOSING; // Just in case...???
descP->isReadable = FALSE;
descP->isWritable = FALSE;
@@ -17692,9 +17636,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
env, descP, &descP->currentWriter.mon);
SSDBG( descP, ("SOCKET", "socket_stop -> handle current writer\r\n") );
- if (!compare_pids(env,
- &descP->closerPid,
- &descP->currentWriter.pid)) {
+ if (COMPARE_PIDS(&descP->closerPid, &descP->currentWriter.pid) != 0) {
SSDBG( descP, ("SOCKET", "socket_stop -> "
"send abort message to current writer %T\r\n",
descP->currentWriter.pid) );
@@ -17715,7 +17657,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
/* And also deal with the waiting writers (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting writer(s)\r\n") );
- inform_waiting_procs(env, descP, &descP->writersQ, TRUE, atom_closed);
+ inform_waiting_procs(env, "writer",
+ descP, &descP->writersQ, TRUE, atom_closed);
}
@@ -17736,12 +17679,15 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
env, descP, &descP->currentReader.mon);
SSDBG( descP, ("SOCKET", "socket_stop -> handle current reader\r\n") );
- if (!compare_pids(env,
- &descP->closerPid,
- &descP->currentReader.pid)) {
+ if (COMPARE_PIDS(&descP->closerPid, &descP->currentReader.pid) != 0) {
SSDBG( descP, ("SOCKET", "socket_stop -> "
"send abort message to current reader %T\r\n",
descP->currentReader.pid) );
+ /*
+ esock_dbg_printf("SOCKET", "socket_stop -> "
+ "send abort message to current reader %T\r\n",
+ descP->currentReader.pid);
+ */
if (esock_send_abort_msg(env,
sockRef,
descP->currentReader.ref,
@@ -17759,7 +17705,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
/* And also deal with the waiting readers (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting reader(s)\r\n") );
- inform_waiting_procs(env, descP, &descP->readersQ, TRUE, atom_closed);
+ inform_waiting_procs(env, "reader",
+ descP, &descP->readersQ, TRUE, atom_closed);
}
@@ -17780,9 +17727,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
env, descP, &descP->currentAcceptor.mon);
SSDBG( descP, ("SOCKET", "socket_stop -> handle current acceptor\r\n") );
- if (!compare_pids(env,
- &descP->closerPid,
- &descP->currentAcceptor.pid)) {
+ if (COMPARE_PIDS(&descP->closerPid, &descP->currentAcceptor.pid) != 0) {
SSDBG( descP, ("SOCKET", "socket_stop -> "
"send abort message to current acceptor %T\r\n",
descP->currentWriter.pid) );
@@ -17803,7 +17748,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
/* And also deal with the waiting acceptors (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting acceptor(s)\r\n") );
- inform_waiting_procs(env, descP, &descP->acceptorsQ, TRUE, atom_closed);
+ inform_waiting_procs(env, "acceptor",
+ descP, &descP->acceptorsQ, TRUE, atom_closed);
}
@@ -17859,15 +17805,24 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* and if the 'free' argument is TRUE, the queue will be emptied.
*/
#if !defined(__WIN32__)
-static
-void inform_waiting_procs(ErlNifEnv* env,
- SocketDescriptor* descP,
- SocketRequestQueue* q,
- BOOLEAN_T free,
- ERL_NIF_TERM reason)
+static void inform_waiting_procs(ErlNifEnv* env,
+ char* role,
+ SocketDescriptor* descP,
+ SocketRequestQueue* q,
+ BOOLEAN_T free,
+ ERL_NIF_TERM reason)
{
SocketRequestQueueElement* currentP = q->first;
SocketRequestQueueElement* nextP;
+ ERL_NIF_TERM sockRef = enif_make_resource(env, descP);
+
+ /*
+ esock_dbg_printf("SOCKET", "inform_waiting_procs -> entry with: "
+ "\r\n role: %s"
+ "\r\n free: %s"
+ "\r\n reason: %T"
+ "\r\n", role, B2S(free), reason);
+ */
while (currentP != NULL) {
@@ -17884,11 +17839,25 @@ void inform_waiting_procs(ErlNifEnv* env,
("SOCKET", "inform_waiting_procs -> abort request %T (from %T)\r\n",
currentP->data.ref, currentP->data.pid) );
- ESOCK_ASSERT( (NULL == esock_send_abort_msg(env,
- esock_atom_undefined,
- currentP->data.ref,
- reason,
- &currentP->data.pid)) );
+ /*
+ esock_dbg_printf("SOCKET", "inform_waiting_procs -> "
+ "try sending abort to %s %T "
+ "\r\n", role, currentP->data.pid);
+ */
+
+ if (esock_send_abort_msg(env,
+ sockRef,
+ currentP->data.ref,
+ reason,
+ &currentP->data.pid) != NULL) {
+
+ esock_warning_msg("Failed sending abort (%T) message to "
+ "current %s %T\r\n",
+ currentP->data.ref,
+ role,
+ currentP->data.pid);
+
+ }
DEMONP("inform_waiting_procs -> current 'request'",
env, descP, &currentP->data.mon);
@@ -17918,6 +17887,7 @@ void socket_down(ErlNifEnv* env,
#if !defined(__WIN32__)
SocketDescriptor* descP = (SocketDescriptor*) obj;
int sres;
+ ERL_NIF_TERM sockRef;
SSDBG( descP, ("SOCKET", "socket_down -> entry with"
"\r\n sock: %d"
@@ -17930,7 +17900,7 @@ void socket_down(ErlNifEnv* env,
if (!IS_CLOSED(descP)) {
- if (compare_pids(env, &descP->ctrlPid, pid)) {
+ if (COMPARE_PIDS(&descP->ctrlPid, pid) == 0) {
/* We don't bother with the queue cleanup here -
* we leave it to the stop callback function.
@@ -18019,7 +17989,7 @@ void socket_down(ErlNifEnv* env,
"\r\n Descriptor: %d"
"\r\n Monitor: %T"
"\r\n", sres, pid, descP->sock,
- my_make_monitor_term(env, mon));
+ MON2T(env, mon));
}
} else {
@@ -18032,19 +18002,21 @@ void socket_down(ErlNifEnv* env,
SSDBG( descP, ("SOCKET", "socket_down -> other process term\r\n") );
+ sockRef = enif_make_resource(env, descP);
+
MLOCK(descP->accMtx);
if (descP->currentAcceptorP != NULL)
- socket_down_acceptor(env, descP, pid);
+ socket_down_acceptor(env, descP, sockRef, pid);
MUNLOCK(descP->accMtx);
MLOCK(descP->writeMtx);
if (descP->currentWriterP != NULL)
- socket_down_writer(env, descP, pid);
+ socket_down_writer(env, descP, sockRef, pid);
MUNLOCK(descP->writeMtx);
MLOCK(descP->readMtx);
if (descP->currentReaderP != NULL)
- socket_down_reader(env, descP, pid);
+ socket_down_reader(env, descP, sockRef, pid);
MUNLOCK(descP->readMtx);
}
@@ -18066,49 +18038,28 @@ void socket_down(ErlNifEnv* env,
static
void socket_down_acceptor(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
{
- if (compare_pids(env, &descP->currentAcceptor.pid, pid)) {
+ if (COMPARE_PIDS(&descP->currentAcceptor.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
"socket_down_acceptor -> "
- "current acceptor - try pop the queue\r\n") );
+ "current acceptor - try activate next\r\n") );
- if (acceptor_pop(env, descP,
- &descP->currentAcceptor.pid,
- &descP->currentAcceptor.mon,
- &descP->currentAcceptor.ref)) {
- int res;
-
- /* There was another one, so we will still be in accepting state */
-
- SSDBG( descP, ("SOCKET",
- "socket_down_acceptor -> new (active) acceptor: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentAcceptor.pid,
- descP->currentAcceptor.ref) );
-
- if ((res = esock_select_read(env, descP->sock, descP,
- &descP->currentAcceptor.pid,
- descP->currentAcceptor.ref) < 0)) {
-
- esock_warning_msg("Failed select (%d) for new acceptor "
- "after current (%T) died\r\n",
- res, *pid);
-
- }
-
- } else {
-
- SSDBG( descP, ("SOCKET",
- "socket_down_acceptor -> no active acceptor\r\n") );
-
- descP->currentAcceptorP = NULL;
- descP->state = SOCKET_STATE_LISTENING;
+ if (!activate_next_acceptor(env, descP, sockRef)) {
+
+ SSDBG( descP,
+ ("SOCKET", "socket_down_acceptor -> no more writers\r\n") );
+
+ descP->state = SOCKET_STATE_LISTENING;
+
+ descP->currentAcceptorP = NULL;
+ descP->currentAcceptor.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ esock_monitor_init(&descP->currentAcceptor.mon);
}
-
+
} else {
/* Maybe unqueue one of the waiting acceptors */
@@ -18132,45 +18083,22 @@ void socket_down_acceptor(ErlNifEnv* env,
static
void socket_down_writer(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
{
- if (compare_pids(env, &descP->currentWriter.pid, pid)) {
+ if (COMPARE_PIDS(&descP->currentWriter.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
"socket_down_writer -> "
- "current writer - try pop the queue\r\n") );
+ "current writer - try activate next\r\n") );
- if (writer_pop(env, descP,
- &descP->currentWriter.pid,
- &descP->currentWriter.mon,
- &descP->currentWriter.ref)) {
- int res;
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "socket_down_writer -> new (current) writer: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentWriter.pid,
- descP->currentWriter.ref) );
-
- if ((res = esock_select_write(env, descP->sock, descP,
- &descP->currentWriter.pid,
- descP->currentWriter.ref) < 0)) {
-
- esock_warning_msg("Failed select (%d) for new writer "
- "after current (%T) died\r\n",
- res, *pid);
-
- }
-
- } else {
-
+ if (!activate_next_writer(env, descP, sockRef)) {
SSDBG( descP, ("SOCKET",
"socket_down_writer -> no active writer\r\n") );
-
- descP->currentWriterP = NULL;
+ descP->currentWriterP = NULL;
+ descP->currentWriter.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentWriter.pid);
+ esock_monitor_init(&descP->currentWriter.mon);
}
} else {
@@ -18196,47 +18124,24 @@ void socket_down_writer(ErlNifEnv* env,
static
void socket_down_reader(ErlNifEnv* env,
SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
{
- if (compare_pids(env, &descP->currentReader.pid, pid)) {
+ if (COMPARE_PIDS(&descP->currentReader.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
"socket_down_reader -> "
- "current reader - try pop the queue\r\n") );
+ "current reader - try activate next\r\n") );
- if (reader_pop(env, descP,
- &descP->currentReader.pid,
- &descP->currentReader.mon,
- &descP->currentReader.ref)) {
- int res;
-
- /* There was another one */
-
- SSDBG( descP, ("SOCKET", "socket_down_reader -> new (current) reader: "
- "\r\n pid: %T"
- "\r\n ref: %T"
- "\r\n",
- descP->currentReader.pid,
- descP->currentReader.ref) );
-
- if ((res = esock_select_read(env, descP->sock, descP,
- &descP->currentReader.pid,
- descP->currentReader.ref) < 0)) {
-
- esock_warning_msg("Failed select (%d) for new reader "
- "after current (%T) died\r\n",
- res, *pid);
-
- }
-
- } else {
-
- SSDBG( descP, ("SOCKET",
- "socket_down_reader -> no active reader\r\n") );
-
- descP->currentReaderP = NULL;
+ if (!activate_next_reader(env, descP, sockRef)) {
+ SSDBG( descP,
+ ("SOCKET", "ncancel_recv_current -> no more readers\r\n") );
+ descP->currentReaderP = NULL;
+ descP->currentReader.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentReader.pid);
+ esock_monitor_init(&descP->currentReader.mon);
}
-
+
} else {
/* Maybe unqueue one of the waiting reader(s) */
@@ -18358,284 +18263,18 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
data.numProtoSCTP = 0;
#endif
- /* +++ Misc atoms +++ */
- atom_adaptation_layer = MKA(env, str_adaptation_layer);
- atom_address = MKA(env, str_address);
- atom_association = MKA(env, str_association);
- atom_assoc_id = MKA(env, str_assoc_id);
- atom_authentication = MKA(env, str_authentication);
- atom_bool = MKA(env, str_bool);
- atom_close = MKA(env, str_close);
- atom_closed = MKA(env, str_closed);
- atom_closing = MKA(env, str_closing);
- atom_cookie_life = MKA(env, str_cookie_life);
- atom_data_in = MKA(env, str_data_in);
- atom_do = MKA(env, str_do);
- atom_dont = MKA(env, str_dont);
- atom_exclude = MKA(env, str_exclude);
- atom_false = MKA(env, str_false);
- atom_global_counters = MKA(env, str_global_counters);
- atom_in4_sockaddr = MKA(env, str_in4_sockaddr);
- atom_in6_sockaddr = MKA(env, str_in6_sockaddr);
- atom_include = MKA(env, str_include);
- atom_initial = MKA(env, str_initial);
- atom_int = MKA(env, str_int);
- atom_interface = MKA(env, str_interface);
- atom_iow = MKA(env, str_iow);
- atom_local_rwnd = MKA(env, str_local_rwnd);
- atom_max = MKA(env, str_max);
- atom_max_attempts = MKA(env, str_max_attempts);
- atom_max_init_timeo = MKA(env, str_max_init_timeo);
- atom_max_instreams = MKA(env, str_max_instreams);
- atom_max_rxt = MKA(env, str_max_rxt);
- atom_min = MKA(env, str_min);
- atom_mode = MKA(env, str_mode);
- atom_multiaddr = MKA(env, str_multiaddr);
- // atom_nif_abort = MKA(env, str_nif_abort);
- atom_null = MKA(env, str_null);
- atom_num_dinet = MKA(env, str_num_dinet);
- atom_num_dinet6 = MKA(env, str_num_dinet6);
- atom_num_dlocal = MKA(env, str_num_dlocal);
- atom_num_outstreams = MKA(env, str_num_outstreams);
- atom_num_peer_dests = MKA(env, str_num_peer_dests);
- atom_num_pip = MKA(env, str_num_pip);
- atom_num_psctp = MKA(env, str_num_psctp);
- atom_num_ptcp = MKA(env, str_num_ptcp);
- atom_num_pudp = MKA(env, str_num_pudp);
- atom_num_sockets = MKA(env, str_num_sockets);
- atom_num_tdgrams = MKA(env, str_num_tdgrams);
- atom_num_tseqpkgs = MKA(env, str_num_tseqpkgs);
- atom_num_tstreams = MKA(env, str_num_tstreams);
- atom_partial_delivery = MKA(env, str_partial_delivery);
- atom_peer_rwnd = MKA(env, str_peer_rwnd);
- atom_peer_error = MKA(env, str_peer_error);
- atom_probe = MKA(env, str_probe);
- atom_select = MKA(env, str_select);
- atom_sender_dry = MKA(env, str_sender_dry);
- atom_send_failure = MKA(env, str_send_failure);
- atom_shutdown = MKA(env, str_shutdown);
- atom_slist = MKA(env, str_slist);
- atom_sourceaddr = MKA(env, str_sourceaddr);
- atom_timeout = MKA(env, str_timeout);
- atom_true = MKA(env, str_true);
- atom_want = MKA(env, str_want);
-
- /* Global atom(s) */
- esock_atom_abort = MKA(env, "abort");
- esock_atom_accept = MKA(env, "accept");
- esock_atom_acceptconn = MKA(env, "acceptconn");
- esock_atom_acceptfilter = MKA(env, "acceptfilter");
- esock_atom_adaption_layer = MKA(env, "adaption_layer");
- esock_atom_addr = MKA(env, "addr");
- esock_atom_addrform = MKA(env, "addrform");
- esock_atom_add_membership = MKA(env, "add_membership");
- esock_atom_add_source_membership = MKA(env, "add_source_membership");
- esock_atom_any = MKA(env, "any");
- esock_atom_associnfo = MKA(env, "associnfo");
- esock_atom_authhdr = MKA(env, "authhdr");
- esock_atom_auth_active_key = MKA(env, "auth_active_key");
- esock_atom_auth_asconf = MKA(env, "auth_asconf");
- esock_atom_auth_chunk = MKA(env, "auth_chunk");
- esock_atom_auth_delete_key = MKA(env, "auth_delete_key");
- esock_atom_auth_key = MKA(env, "auth_key");
- esock_atom_auth_level = MKA(env, "auth_level");
- esock_atom_autoclose = MKA(env, "autoclose");
- esock_atom_bindtodevice = MKA(env, "bindtodevice");
- esock_atom_block_source = MKA(env, "block_source");
- esock_atom_broadcast = MKA(env, "broadcast");
- esock_atom_busy_poll = MKA(env, "busy_poll");
- esock_atom_checksum = MKA(env, "checksum");
- esock_atom_close = MKA(env, "close");
- esock_atom_connect = MKA(env, "connect");
- esock_atom_congestion = MKA(env, "congestion");
- esock_atom_context = MKA(env, "context");
- esock_atom_cork = MKA(env, "cork");
- esock_atom_credentials = MKA(env, "credentials");
- esock_atom_ctrl = MKA(env, "ctrl");
- esock_atom_ctrunc = MKA(env, "ctrunc");
- esock_atom_data = MKA(env, "data");
- esock_atom_debug = MKA(env, "debug");
- esock_atom_default_send_params = MKA(env, "default_send_params");
- esock_atom_delayed_ack_time = MKA(env, "delayed_ack_time");
- esock_atom_dgram = MKA(env, "dgram");
- esock_atom_disable_fragments = MKA(env, "disable_fragments");
- esock_atom_domain = MKA(env, "domain");
- esock_atom_dontfrag = MKA(env, "dontfrag");
- esock_atom_dontroute = MKA(env, "dontroute");
- esock_atom_drop_membership = MKA(env, "drop_membership");
- esock_atom_drop_source_membership = MKA(env, "drop_source_membership");
- esock_atom_dstopts = MKA(env, "dstpopts");
- esock_atom_eor = MKA(env, "eor");
- esock_atom_error = MKA(env, "error");
- esock_atom_errqueue = MKA(env, "errqueue");
- esock_atom_esp_network_level = MKA(env, "esp_network_level");
- esock_atom_esp_trans_level = MKA(env, "esp_trans_level");
- esock_atom_events = MKA(env, "events");
- esock_atom_explicit_eor = MKA(env, "explicit_eor");
- esock_atom_faith = MKA(env, "faith");
- esock_atom_false = MKA(env, "false");
- esock_atom_family = MKA(env, "family");
- esock_atom_flags = MKA(env, "flags");
- esock_atom_flowinfo = MKA(env, "flowinfo");
- esock_atom_fragment_interleave = MKA(env, "fragment_interleave");
- esock_atom_freebind = MKA(env, "freebind");
- esock_atom_get_peer_addr_info = MKA(env, "get_peer_addr_info");
- esock_atom_hdrincl = MKA(env, "hdrincl");
- esock_atom_hmac_ident = MKA(env, "hmac_ident");
- esock_atom_hoplimit = MKA(env, "hoplimit");
- esock_atom_hopopts = MKA(env, "hopopts");
- esock_atom_ifindex = MKA(env, "ifindex");
- esock_atom_inet = MKA(env, "inet");
- esock_atom_inet6 = MKA(env, "inet6");
- esock_atom_info = MKA(env, "info");
- esock_atom_initmsg = MKA(env, "initmsg");
- esock_atom_iov = MKA(env, "iov");
- esock_atom_ip = MKA(env, "ip");
- esock_atom_ipcomp_level = MKA(env, "ipcomp_level");
- esock_atom_ipv6 = MKA(env, "ipv6");
- esock_atom_i_want_mapped_v4_addr = MKA(env, "i_want_mapped_v4_addr");
- esock_atom_join_group = MKA(env, "join_group");
- esock_atom_keepalive = MKA(env, "keepalive");
- esock_atom_keepcnt = MKA(env, "keepcnt");
- esock_atom_keepidle = MKA(env, "keepidle");
- esock_atom_keepintvl = MKA(env, "keepintvl");
- esock_atom_leave_group = MKA(env, "leave_group");
- esock_atom_level = MKA(env, "level");
- esock_atom_linger = MKA(env, "linger");
- esock_atom_local = MKA(env, "local");
- esock_atom_local_auth_chunks = MKA(env, "local_auth_chunks");
- esock_atom_loopback = MKA(env, "loopback");
- esock_atom_lowdelay = MKA(env, "lowdelay");
- esock_atom_mark = MKA(env, "mark");
- esock_atom_maxburst = MKA(env, "maxburst");
- esock_atom_maxseg = MKA(env, "maxseg");
- esock_atom_md5sig = MKA(env, "md5sig");
- esock_atom_mincost = MKA(env, "mincost");
- esock_atom_minttl = MKA(env, "minttl");
- esock_atom_msfilter = MKA(env, "msfilter");
- esock_atom_mtu = MKA(env, "mtu");
- esock_atom_mtu_discover = MKA(env, "mtu_discover");
- esock_atom_multicast_all = MKA(env, "multicast_all");
- esock_atom_multicast_hops = MKA(env, "multicast_hops");
- esock_atom_multicast_if = MKA(env, "multicast_if");
- esock_atom_multicast_loop = MKA(env, "multicast_loop");
- esock_atom_multicast_ttl = MKA(env, "multicast_ttl");
- esock_atom_nodefrag = MKA(env, "nodefrag");
- esock_atom_nodelay = MKA(env, "nodelay");
- esock_atom_noopt = MKA(env, "noopt");
- esock_atom_nopush = MKA(env, "nopush");
- esock_atom_not_found = MKA(env, "not_found");
- esock_atom_not_owner = MKA(env, "not_owner");
- esock_atom_ok = MKA(env, "ok");
- esock_atom_oob = MKA(env, "oob");
- esock_atom_oobinline = MKA(env, "oobinline");
- esock_atom_options = MKA(env, "options");
- esock_atom_origdstaddr = MKA(env, "origdstaddr");
- esock_atom_partial_delivery_point = MKA(env, "partial_delivery_point");
- esock_atom_passcred = MKA(env, "passcred");
- esock_atom_path = MKA(env, "path");
- esock_atom_peekcred = MKA(env, "peekcred");
- esock_atom_peek_off = MKA(env, "peek_off");
- esock_atom_peer_addr_params = MKA(env, "peer_addr_params");
- esock_atom_peer_auth_chunks = MKA(env, "peer_auth_chunks");
- esock_atom_pktinfo = MKA(env, "pktinfo");
- esock_atom_pktoptions = MKA(env, "pktoptions");
- esock_atom_port = MKA(env, "port");
- esock_atom_portrange = MKA(env, "portrange");
- esock_atom_primary_addr = MKA(env, "primary_addr");
- esock_atom_priority = MKA(env, "priority");
- esock_atom_protocol = MKA(env, "protocol");
- esock_atom_raw = MKA(env, "raw");
- esock_atom_rcvbuf = MKA(env, "rcvbuf");
- esock_atom_rcvbufforce = MKA(env, "rcvbufforce");
- esock_atom_rcvlowat = MKA(env, "rcvlowat");
- esock_atom_rcvtimeo = MKA(env, "rcvtimeo");
- esock_atom_rdm = MKA(env, "rdm");
- esock_atom_recv = MKA(env, "recv");
- esock_atom_recvdstaddr = MKA(env, "recvdstaddr");
- esock_atom_recverr = MKA(env, "recverr");
- esock_atom_recvfrom = MKA(env, "recvfrom");
- esock_atom_recvif = MKA(env, "recvif");
- esock_atom_recvmsg = MKA(env, "recvmsg");
- esock_atom_recvopts = MKA(env, "recvopts");
- esock_atom_recvorigdstaddr = MKA(env, "recvorigdstaddr");
- esock_atom_recvpktinfo = MKA(env, "recvpktinfo");
- esock_atom_recvtclass = MKA(env, "recvtclass");
- esock_atom_recvtos = MKA(env, "recvtos");
- esock_atom_recvttl = MKA(env, "recvttl");
- esock_atom_reliability = MKA(env, "reliability");
- esock_atom_reset_streams = MKA(env, "reset_streams");
- esock_atom_retopts = MKA(env, "retopts");
- esock_atom_reuseaddr = MKA(env, "reuseaddr");
- esock_atom_reuseport = MKA(env, "reuseport");
- esock_atom_rights = MKA(env, "rights");
- esock_atom_router_alert = MKA(env, "router_alert");
- esock_atom_rthdr = MKA(env, "rthdr");
- esock_atom_rtoinfo = MKA(env, "rtoinfo");
- esock_atom_rxq_ovfl = MKA(env, "rxq_ovfl");
- esock_atom_scope_id = MKA(env, "scope_id");
- esock_atom_sctp = MKA(env, "sctp");
- esock_atom_sec = MKA(env, "sec");
- esock_atom_select_failed = MKA(env, "select_failed");
- esock_atom_select_sent = MKA(env, "select_sent");
- esock_atom_send = MKA(env, "send");
- esock_atom_sendmsg = MKA(env, "sendmsg");
- esock_atom_sendsrcaddr = MKA(env, "sendsrcaddr");
- esock_atom_sendto = MKA(env, "sendto");
- esock_atom_seqpacket = MKA(env, "seqpacket");
- esock_atom_setfib = MKA(env, "setfib");
- esock_atom_set_peer_primary_addr = MKA(env, "set_peer_primary_addr");
- esock_atom_sndbuf = MKA(env, "sndbuf");
- esock_atom_sndbufforce = MKA(env, "sndbufforce");
- esock_atom_sndlowat = MKA(env, "sndlowat");
- esock_atom_sndtimeo = MKA(env, "sndtimeo");
- esock_atom_socket = MKA(env, "socket");
- esock_atom_socket_tag = MKA(env, "$socket");
- esock_atom_spec_dst = MKA(env, "spec_dst");
- esock_atom_status = MKA(env, "status");
- esock_atom_stream = MKA(env, "stream");
- esock_atom_syncnt = MKA(env, "syncnt");
- esock_atom_tclass = MKA(env, "tclass");
- esock_atom_tcp = MKA(env, "tcp");
- esock_atom_throughput = MKA(env, "throughput");
- esock_atom_timestamp = MKA(env, "timestamp");
- esock_atom_tos = MKA(env, "tos");
- esock_atom_transparent = MKA(env, "transparent");
- esock_atom_true = MKA(env, "true");
- esock_atom_trunc = MKA(env, "trunc");
- esock_atom_ttl = MKA(env, "ttl");
- esock_atom_type = MKA(env, "type");
- esock_atom_udp = MKA(env, "udp");
- esock_atom_unblock_source = MKA(env, "unblock_source");
- esock_atom_undefined = MKA(env, "undefined");
- esock_atom_unicast_hops = MKA(env, "unicast_hops");
- esock_atom_unknown = MKA(env, "unknown");
- esock_atom_usec = MKA(env, "usec");
- esock_atom_user_timeout = MKA(env, "user_timeout");
- esock_atom_use_ext_recvinfo = MKA(env, "use_ext_recvinfo");
- esock_atom_use_min_mtu = MKA(env, "use_min_mtu");
- esock_atom_v6only = MKA(env, "v6only");
-
- /* Global error codes */
- esock_atom_eafnosupport = MKA(env, ESOCK_STR_EAFNOSUPPORT);
- esock_atom_eagain = MKA(env, ESOCK_STR_EAGAIN);
- esock_atom_einval = MKA(env, ESOCK_STR_EINVAL);
-
- /* Error codes */
- atom_eisconn = MKA(env, str_eisconn);
- atom_enotclosing = MKA(env, str_enotclosing);
- atom_enotconn = MKA(env, str_enotconn);
- atom_exalloc = MKA(env, str_exalloc);
- atom_exbadstate = MKA(env, str_exbadstate);
- atom_exbusy = MKA(env, str_exbusy);
- atom_exmon = MKA(env, str_exmon);
- atom_exself = MKA(env, str_exself);
- atom_exsend = MKA(env, str_exsend);
-
- // For storing "global" things...
- // data.env = enif_alloc_env(); // We should really check
- // data.version = MKA(env, ERTS_VERSION);
- // data.buildDate = MKA(env, ERTS_BUILD_DATE);
+ /* +++ Local atoms and error reason atoms +++ */
+#define LOCAL_ATOM_DECL(A) atom_##A = MKA(env, #A)
+LOCAL_ATOMS
+LOCAL_ERROR_REASON_ATOMS
+#undef LOCAL_ATOM_DECL
+
+ /* Global atom(s) and error reason atom(s) */
+#define GLOBAL_ATOM_DECL(A) esock_atom_##A = MKA(env, #A)
+GLOBAL_ATOMS
+GLOBAL_ERROR_REASON_ATOMS
+#undef GLOBAL_ATOM_DECL
+ esock_atom_socket_tag = MKA(env, "$socket");
sockets = enif_open_resource_type_x(env,
"sockets",
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index f6e4781977..b817ae7636 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -177,7 +177,7 @@ char* esock_decode_iov(ErlNifEnv* env,
return ESOCK_STR_EINVAL;
if (IS_BIN(env, elem) && GET_BIN(env, elem, &bufs[i])) {
- iov[i].iov_base = bufs[i].data;
+ iov[i].iov_base = (caddr_t) bufs[i].data;
iov[i].iov_len = bufs[i].size;
sz += bufs[i].size;
} else {
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 4a0ad9c1d5..2309f844b9 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -65,7 +65,8 @@
nif_whereis/1, nif_whereis_parallel/1,
nif_whereis_threaded/1, nif_whereis_proxy/1,
nif_ioq/1,
- pid/1
+ pid/1,
+ nif_term_type/1
]).
-export([many_args_100/100]).
@@ -105,7 +106,8 @@ all() ->
nif_phash2,
nif_whereis, nif_whereis_parallel, nif_whereis_threaded,
nif_ioq,
- pid].
+ pid,
+ nif_term_type].
groups() ->
[{G, [], api_repeaters()} || G <- api_groups()]
@@ -3392,6 +3394,41 @@ pid(Config) ->
{false, _} = get_local_pid_nif(undefined),
ok.
+nif_term_type(Config) ->
+ ensure_lib_loaded(Config),
+
+ atom = term_type_nif(atom),
+
+ bitstring = term_type_nif(<<1:1>>),
+ bitstring = term_type_nif(<<1:8>>),
+
+ float = term_type_nif(0.0),
+
+ 'fun' = term_type_nif(fun external:function/1),
+ 'fun' = term_type_nif(fun(A) -> A end),
+ 'fun' = term_type_nif(fun id/1),
+
+ integer = term_type_nif(1 bsl 1024), %Bignum.
+ integer = term_type_nif(1),
+
+ list = term_type_nif([list]),
+ list = term_type_nif([]),
+
+ LargeMap = maps:from_list([{N, N} || N <- lists:seq(1, 256)]),
+ map = term_type_nif(LargeMap),
+ map = term_type_nif(#{ small => map }),
+
+ pid = term_type_nif(self()),
+
+ Port = open_port({spawn,echo_drv},[eof]),
+ port = term_type_nif(Port),
+ port_close(Port),
+
+ reference = term_type_nif(make_ref()),
+
+ tuple = term_type_nif({}),
+
+ ok.
id(I) -> I.
@@ -3507,5 +3544,7 @@ set_pid_undefined_nif() -> ?nif_stub.
is_pid_undefined_nif(_) -> ?nif_stub.
compare_pids_nif(_, _) -> ?nif_stub.
+term_type_nif(_) -> ?nif_stub.
+
nif_stub_error(Line) ->
exit({nif_not_loaded,module,?MODULE,line,Line}).
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 0d5d900d31..1906384af4 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -3583,6 +3583,36 @@ static ERL_NIF_TERM compare_pids_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
return enif_make_int(env, enif_compare_pids(&a, &b));
}
+static ERL_NIF_TERM term_type_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ switch (enif_term_type(env, argv[0])) {
+ case ERL_NIF_TERM_TYPE_ATOM:
+ return enif_make_atom(env, "atom");
+ case ERL_NIF_TERM_TYPE_BITSTRING:
+ return enif_make_atom(env, "bitstring");
+ case ERL_NIF_TERM_TYPE_FLOAT:
+ return enif_make_atom(env, "float");
+ case ERL_NIF_TERM_TYPE_FUN:
+ return enif_make_atom(env, "fun");
+ case ERL_NIF_TERM_TYPE_INTEGER:
+ return enif_make_atom(env, "integer");
+ case ERL_NIF_TERM_TYPE_LIST:
+ return enif_make_atom(env, "list");
+ case ERL_NIF_TERM_TYPE_MAP:
+ return enif_make_atom(env, "map");
+ case ERL_NIF_TERM_TYPE_PID:
+ return enif_make_atom(env, "pid");
+ case ERL_NIF_TERM_TYPE_PORT:
+ return enif_make_atom(env, "port");
+ case ERL_NIF_TERM_TYPE_REFERENCE:
+ return enif_make_atom(env, "reference");
+ case ERL_NIF_TERM_TYPE_TUPLE:
+ return enif_make_atom(env, "tuple");
+ default:
+ return enif_make_badarg(env);
+ }
+}
+
static ErlNifFunc nif_funcs[] =
{
{"lib_version", 0, lib_version},
@@ -3690,7 +3720,8 @@ static ErlNifFunc nif_funcs[] =
{"make_pid_nif", 1, make_pid_nif},
{"set_pid_undefined_nif", 0, set_pid_undefined_nif},
{"is_pid_undefined_nif", 1, is_pid_undefined_nif},
- {"compare_pids_nif", 2, compare_pids_nif}
+ {"compare_pids_nif", 2, compare_pids_nif},
+ {"term_type_nif", 1, term_type_nif}
};
ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload)
diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl
index 52d002c9b8..aec280485c 100644
--- a/erts/emulator/test/socket_SUITE.erl
+++ b/erts/emulator/test/socket_SUITE.erl
@@ -5543,6 +5543,7 @@ sc_lc_receive_response_tcp(InitState) ->
end},
#{desc => "attempt recv (=> closed)",
cmd => fun(#{sock := Sock, recv := Recv} = State) ->
+ %% ok = socket:setopt(Sock, otp, debug, true),
case Recv(Sock) of
{ok, _Data} ->
?SEV_EPRINT("Unexpected data received"),
diff --git a/erts/emulator/test/socket_test_evaluator.erl b/erts/emulator/test/socket_test_evaluator.erl
index fe6a6ff70a..bd86b3b92e 100644
--- a/erts/emulator/test/socket_test_evaluator.erl
+++ b/erts/emulator/test/socket_test_evaluator.erl
@@ -471,7 +471,7 @@ await(ExpPid, Name, Announcement, Slogan, OtherPids)
"~n Announcement: ~p"
"~n Slogan: ~p"
"~nwhen"
- "~n Messages: ~p",
+ "~n Messages: ~p",
[ExpPid, Name, Announcement, Slogan, pi(messages)]),
await(ExpPid, Name, Announcement, Slogan, OtherPids)
end.
diff --git a/erts/vsn.mk b/erts/vsn.mk
index bab5c805eb..fac608ed4e 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 10.2.5
+VSN = 10.3
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 2f53f1c29e..c8e0722a0f 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -33,6 +33,66 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug caused <c>ct:encrypt_config_file/3</c> and
+ <c>ct:decrypt_config_file/3</c> to fail with
+ <c>badmatch</c> if input parameter <c>KeyOrFile</c> was
+ <c>{key,string()}</c>. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15540</p>
+ </item>
+ <item>
+ <p>
+ The status of a test case which failed with timetrap
+ timeout in <c>end_per_testcase</c> could not be modified
+ by returning <c>{fail,Reason}</c> from a
+ <c>post_end_per_testcase</c> hook function. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-15584 Aux Id: ERIERL-282 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new variant of the <c>newline</c> option to
+ <c>ct_telnet:cmd/3</c> and <c>ct_telnet:send/3</c> is
+ added, which allows to specify a string to append as
+ newline indicator on a command. By default, the value is
+ "\n", but in some cases it is required to be "\r\n",
+ which this option allows.</p>
+ <p>
+ A faulty regular expression given as parameter to
+ <c>ct_telnet:expect/2,3</c> would earlier crash and look
+ like an internal error in common_test. A better error
+ indication is now given, but the test case will still
+ fail.</p>
+ <p>
+ Own Id: OTP-15229 Aux Id: ERIERL-203 </p>
+ </item>
+ <item>
+ <p>
+ Since the yang RFC allows more than one top element of
+ config data in an <c>edit-config</c> element,
+ <c>ct_netconfc:edit_config/3,4,5</c> can now take a list
+ of XML elements.</p>
+ <p>
+ Own Id: OTP-15298</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.16.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/test_server/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl
index c2852131d6..f3972bea4e 100644
--- a/lib/common_test/test_server/ts_erl_config.erl
+++ b/lib/common_test/test_server/ts_erl_config.erl
@@ -197,28 +197,24 @@ system_include(Root, Vars) ->
" -I" ++ quote(filename:nativename(filename:join([Root, "erts", "emulator", SysDir]))).
erl_interface(Vars,OsType) ->
- {Incl, TargetIncl, {LibPath, MkIncl}} =
+ {Incl, {LibPath, MkIncl}} =
case lib_dir(Vars, erl_interface) of
{error, bad_name} ->
throw({cannot_find_app, erl_interface});
Dir ->
- BaseIncl = filename:join(Dir, "include"),
- case erl_root(Vars) of
- {installed, _Root} ->
- {BaseIncl,
- [],
- {filename:join(Dir, "lib"),
- filename:join([Dir, "src", "eidefs.mk"])}};
- {srctree, _Root, Target} ->
- Obj = case is_debug_build() of
- true -> "obj.debug";
- false -> "obj"
- end,
- {BaseIncl,
- filename:join(BaseIncl, Target),
- {filename:join([Dir, Obj, Target]),
- filename:join([Dir, "src", Target, "eidefs.mk"])}}
- end
+ {filename:join(Dir, "include"),
+ case erl_root(Vars) of
+ {installed, _Root} ->
+ {filename:join(Dir, "lib"),
+ filename:join([Dir, "src", "eidefs.mk"])};
+ {srctree, _Root, Target} ->
+ Obj = case is_debug_build() of
+ true -> "obj.debug";
+ false -> "obj"
+ end,
+ {filename:join([Dir, Obj, Target]),
+ filename:join([Dir, "src", Target, "eidefs.mk"])}
+ end}
end,
Lib = link_library("erl_interface",OsType),
Lib1 = link_library("ei",OsType),
@@ -264,10 +260,6 @@ erl_interface(Vars,OsType) ->
{erl_interface_eilib_drv, quote(filename:join(LibPath, Lib1Drv))},
{erl_interface_threadlib, ThreadLib},
{erl_interface_include, quote(filename:nativename(Incl))},
- {erl_interface_target_include, case TargetIncl of
- [] -> [];
- _ -> "-I" ++ quote(filename:nativename(TargetIncl))
- end},
{erl_interface_mk_include, quote(filename:nativename(MkIncl))}
| Vars].
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index fd5d4a57aa..23eb8d9656 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.16.1
+COMMON_TEST_VSN = 1.17
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 02e6203137..d45dfef8f3 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,38 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>An expression such as <c>(A / B) band 16#ff</c> would
+ crash the compiler.</p>
+ <p>
+ Own Id: OTP-15518 Aux Id: ERL-829 </p>
+ </item>
+ <item>
+ <p>There could be an incorrect warning when the
+ <c>tuple_calls</c> option was given. The generated code
+ would be correct. Here is an example of code that would
+ trigger the warning:</p>
+ <p><c>(list_to_atom("prefix_" ++
+ atom_to_list(suffix))):doit(X)</c>.</p>
+ <p>
+ Own Id: OTP-15552 Aux Id: ERL-838 </p>
+ </item>
+ <item>
+ <p>Optimize (again) Dialyzer's handling of
+ left-associative use of <c>andalso</c> and <c>orelse</c>
+ in guards.</p>
+ <p>
+ Own Id: OTP-15577 Aux Id: ERL-851, PR-2141, PR-1944 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index bcf55f3fda..90c0d3cf16 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -911,6 +911,11 @@ ssa_opt_float({#st{ssa=Linear0,cnt=Count0}=St, FuncDb}) ->
{Linear,Count} = float_opt(Linear0, Count0, Fs),
{St#st{ssa=Linear,cnt=Count}, FuncDb}.
+float_blk_is_in_guard(#b_blk{last=#b_br{fail=F}}, #fs{non_guards=NonGuards}) ->
+ not gb_sets:is_member(F, NonGuards);
+float_blk_is_in_guard(#b_blk{}, #fs{}) ->
+ false.
+
float_non_guards([{L,#b_blk{is=Is}}|Bs]) ->
case Is of
[#b_set{op=landingpad}|_] ->
@@ -920,21 +925,18 @@ float_non_guards([{L,#b_blk{is=Is}}|Bs]) ->
end;
float_non_guards([]) -> [?BADARG_BLOCK].
-float_opt([{L,#b_blk{last=#b_br{fail=F}}=Blk}|Bs0],
- Count0, #fs{non_guards=NonGuards}=Fs) ->
- case gb_sets:is_member(F, NonGuards) of
+float_opt([{L,Blk}|Bs0], Count0, Fs) ->
+ case float_blk_is_in_guard(Blk, Fs) of
true ->
- %% This block is not inside a guard.
- %% We can do the optimization.
- float_opt_1(L, Blk, Bs0, Count0, Fs);
- false ->
%% This block is inside a guard. Don't do
%% any floating point optimizations.
{Bs,Count} = float_opt(Bs0, Count0, Fs),
- {[{L,Blk}|Bs],Count}
+ {[{L,Blk}|Bs],Count};
+ false ->
+ %% This block is not inside a guard.
+ %% We can do the optimization.
+ float_opt_1(L, Blk, Bs0, Count0, Fs)
end;
-float_opt([{L,Blk}|Bs], Count, Fs) ->
- float_opt_1(L, Blk, Bs, Count, Fs);
float_opt([], Count, _Fs) ->
{[],Count}.
@@ -1010,10 +1012,14 @@ float_conv([{L,#b_blk{is=Is0}=Blk0}|Bs0], Fail, Count0) ->
float_maybe_flush(Blk0, #fs{s=cleared,fail=Fail,bs=Blocks}=Fs0, Count0) ->
#b_blk{last=#b_br{bool=#b_var{},succ=Succ}=Br} = Blk0,
- #b_blk{is=Is} = map_get(Succ, Blocks),
+
+ %% If the success block starts with a floating point operation, we can
+ %% defer flushing to that block as long as it isn't a guard.
+ #b_blk{is=Is} = SuccBlk = map_get(Succ, Blocks),
+ SuccIsGuard = float_blk_is_in_guard(SuccBlk, Fs0),
+
case Is of
- [#b_set{anno=#{float_op:=_}}|_] ->
- %% The next operation is also a floating point operation.
+ [#b_set{anno=#{float_op:=_}}|_] when not SuccIsGuard ->
%% No flush needed.
{[],Blk0,Fs0,Count0};
_ ->
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 831e8279aa..0fa8070dc8 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -21,15 +21,16 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
pending/1,bif_calls/1,math_functions/1,mixed_float_and_int/1,
- subtract_number_type/1]).
+ subtract_number_type/1,float_followed_by_guard/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[pending, bif_calls, math_functions,
- mixed_float_and_int, subtract_number_type].
+ mixed_float_and_int, subtract_number_type,
+ float_followed_by_guard].
groups() ->
[].
@@ -187,5 +188,21 @@ fact(0, P) -> P;
fact(1, P) -> P;
fact(N, P) -> fact(N-1, P*N).
+float_followed_by_guard(Config) when is_list(Config) ->
+ true = ffbg_1(5, 1),
+ false = ffbg_1(1, 5),
+ ok.
+
+ffbg_1(A, B0) ->
+ %% This is a non-guard block followed by a *guard block* that starts with a
+ %% floating point operation, and the compiler erroneously assumed that it
+ %% was safe to skip fcheckerror because the next block started with a float
+ %% op.
+ B = id(B0) / 1.0,
+ if
+ A - B > 0.0 -> true;
+ A - B =< 0.0 -> false
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index efedb414ad..a523627384 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.3.1
+COMPILER_VSN = 7.3.2
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 0a3f68ade2..c0b302734e 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,38 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes a bug that caused <c>crypto:sign</c> and
+ <c>crypto:verify</c> to return the error message
+ <c>badarg</c> instead of <c>notsup</c> in one case. That
+ case was when signing or verifying with eddsa keys (that
+ is, ed15519 or ed448), but only when FIPS was supported
+ and enabled.</p>
+ <p>
+ Own Id: OTP-15634</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added a crypto benchmark test suite.</p>
+ <p>
+ Own Id: OTP-15447</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 6a91244715..deba17fb66 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.4
+CRYPTO_VSN = 4.4.1
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 3cf776e566..bc422c43a0 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -32,6 +32,36 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 3.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug that caused Dialyzer to crash when
+ analyzing a contract with a module name differing from
+ the analyzed module's name. The bug was introduced in
+ Erlang/OTP 18. </p>
+ <p>
+ Own Id: OTP-15562 Aux Id: ERL-845 </p>
+ </item>
+ <item>
+ <p> Fix a bug in the handling of the <c>Key</c> argument
+ of <c>lists:{keysearch, keyfind, keymember}</c>. </p>
+ <p>
+ Own Id: OTP-15570</p>
+ </item>
+ <item>
+ <p>Optimize (again) Dialyzer's handling of
+ left-associative use of <c>andalso</c> and <c>orelse</c>
+ in guards.</p>
+ <p>
+ Own Id: OTP-15577 Aux Id: ERL-851, PR-2141, PR-1944 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 3.3.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 98ab533a58..7221993963 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 3.3.1
+DIALYZER_VSN = 3.3.2
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index cc92bd99f0..5777225ae7 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -43,6 +43,41 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix failure of incoming answer message with faulty
+ Experimental-Result-Code. Failure to decode the AVP
+ resulted in an uncaught exception, with no no
+ handle_answer/error callback as a consequence.</p>
+ <p>
+ Own Id: OTP-15569 Aux Id: ERIERL-302 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add spawn_opt MFA configuration to allow a callback to
+ spawn a handler process for an incoming Diameter request
+ on an an arbitrary node. Module diameter_dist provides a
+ route_session/2 that can be used to distribute requests
+ based on Session-Id, although this module is currently
+ only documented in the module itself and may change.</p>
+ <p>
+ Own Id: OTP-15398</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 8c75c9e55e..a900e8f28e 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.1.6
+DIAMETER_VSN = 2.2
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index e818887eb8..145856bcaa 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.10</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Print a helpful message explaining that adding
+ <c>{preprocess, true}</c> can help if reading a source
+ file fails. </p>
+ <p>
+ Own Id: OTP-15605 Aux Id: ERL-841 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.9.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 0b3636f030..b6e1422623 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.9.4
+EDOC_VSN = 0.10
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 97c842a324..54f0a36b27 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -31,7 +31,31 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.8.1</title>
+ <section><title>Erl_Docgen 0.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The HTML reference documentation shows the OTP version
+ where modules and functions were first introduced.
+ Versions older than R13B04 are not shown.</p>
+ <p>
+ Own Id: OTP-15460</p>
+ </item>
+ <item>
+ <p>
+ Make html documentation of C functions with many
+ arguments more readable.</p>
+ <p>
+ Own Id: OTP-15637 Aux Id: PR-2160 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 3b2f6db6a1..6321f229dd 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.8.1
+ERL_DOCGEN_VSN = 0.9
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index 67acb7c180..f0e9b2eb3f 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -61,7 +61,7 @@ fi
TARGET=$host
AC_SUBST(TARGET)
-AC_CONFIG_HEADER([src/$host/config.h:config.h.in include/$host/ei_config.h:include/ei_config.h.in])
+AC_CONFIG_HEADER([src/$host/config.h:config.h.in])
dnl ----------------------------------------------------------------------
dnl Optional features
@@ -184,14 +184,6 @@ AC_TRY_COMPILE([#include <sys/types.h>
AC_DEFINE(HAVE_SOCKLEN_T, [], [Define if you have the `socklen_t' type])],
[AC_MSG_RESULT(no)])
-AC_MSG_CHECKING([for deprecated attribute])
-AC_TRY_COMPILE([],
-[void my_function(void) __attribute__((deprecated));],
-[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_DEPRECATED_ATTRIBUTE, [1], [Define to 1 if you have the `deprecated' attribute])],
-[AC_MSG_RESULT(no)])
-
-
# Checks for library functions.
AC_FUNC_ALLOCA
dnl AC_FUNC_FORK
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index 2bdb390644..f081ca926a 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -736,7 +736,7 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_init(void)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_init(void)</nametext></name>
<fsummary>Initialize the ei library.</fsummary>
<desc>
<p>Initialize the <c>ei</c> library. This function should be called once
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index df40973270..795f1249b3 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -412,7 +412,7 @@ typedef struct {
</func>
<func>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_close_connection(int fd)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_close_connection(int fd)</nametext></name>
<fsummary>Close a connection.</fsummary>
<desc>
<p>Closes a previously opened connection or listen socket.</p>
@@ -472,9 +472,9 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
<func>
<name since=""><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation)</nametext></name>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
<name since=""><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation)</nametext></name>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
<fsummary>Initialize for a connection.</fsummary>
<desc>
<p>Initializes the <c>ec</c> structure, to
@@ -595,8 +595,8 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_listen(ei_cnode *ec, int *port, int backlog)</nametext></name>
- <name since="OTP @OTP-15442@"><ret>int</ret><nametext>ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_listen(ei_cnode *ec, int *port, int backlog)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog)</nametext></name>
<fsummary>Create a listen socket.</fsummary>
<desc>
<p>Used by a server process to setup a listen socket which
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 07ddd82718..b686cfbf33 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,23 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support for plugin of a <seealso
+ marker="ei_connect#ussi">user supplied socket
+ implementation</seealso> has been added.</p>
+ <p>
+ Own Id: OTP-15442 Aux Id: ERIERL-258 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index 10a6e5bf50..aa2a49098f 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -47,21 +47,26 @@ typedef LONG_PTR ssize_t; /* Sigh... */
# include <netdb.h>
#endif
-#ifndef EI_INCLUDED_CONFIG_H__
-#include "ei_config.h"
+#ifdef __has_attribute
+#if __has_attribute(deprecated)
+#define EI_HAVE_DEPRECATED_ATTR__ 1
+#else
+#undef EI_HAVE_DEPRECATED_ATTR__
+#endif
#endif
-#if defined(HAVE_DEPRECATED_ATTRIBUTE) && !defined(EI_NO_DEPR_WARN)
-#define EI_HAVE_DEPRECATED_ATTR__ 1
+#ifdef EI_NO_DEPR_WARN
+#undef EI_HAVE_DEPRECATED_ATTR__
+#endif
+
+#ifdef EI_HAVE_DEPRECATED_ATTR__
#define EI_DEPRECATED_ATTR_NAME deprecated
#define EI_DEPRECATED_ATTR __attribute__((EI_DEPRECATED_ATTR_NAME))
#else
-#undef EI_HAVE_DEPRECATED_ATTR__
#define EI_DEPRECATED_ATTR_NAME
#define EI_DEPRECATED_ATTR
#endif
-
/* -------------------------------------------------------------------- */
/* Defines part of API */
/* -------------------------------------------------------------------- */
diff --git a/lib/erl_interface/include/ei_config.h.in b/lib/erl_interface/include/ei_config.h.in
deleted file mode 100644
index dfcf676bed..0000000000
--- a/lib/erl_interface/include/ei_config.h.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-/* Define to 1 if you have the `deprecated' attribute */
-#undef HAVE_DEPRECATED_ATTRIBUTE
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 1b19a85f1e..b2600f0fab 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -118,7 +118,7 @@ else
AR_FLAGS=rcv
endif
-INCFLAGS = -I. -I../include -I../include/$(TARGET) -Iconnect -Iencode -Idecode -Imisc -Iepmd \
+INCFLAGS = -I. -I../include -Iconnect -Iencode -Idecode -Imisc -Iepmd \
-Iregistry -I$(TARGET)
ifeq ($(USING_VC),yes)
@@ -322,8 +322,7 @@ HEADERS = \
../include/ei.h \
../include/ei_connect.h \
../include/eicode.h \
- ../include/erl_interface.h \
- ../include/$(TARGET)/ei_config.h
+ ../include/erl_interface.h
EISOURCES = \
$(CONNECTSRC) \
diff --git a/lib/erl_interface/src/misc/eidef.h b/lib/erl_interface/src/misc/eidef.h
index 083814c6e9..f38824d826 100644
--- a/lib/erl_interface/src/misc/eidef.h
+++ b/lib/erl_interface/src/misc/eidef.h
@@ -25,7 +25,6 @@
/* Common definitions used in ei user interface */
-#define EI_INCLUDED_CONFIG_H__
#include "config.h" /* Central include of config.h */
/* vxWorks.h needs to be before stddef.h */
diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.src b/lib/erl_interface/test/all_SUITE_data/Makefile.src
index 57e522fd3e..4f27b097c8 100644
--- a/lib/erl_interface/test/all_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src
@@ -21,8 +21,8 @@ include @erl_interface_mk_include@
CC0 = @CC@
CC = .@DS@gccifier@exe@ -CC"$(CC0)"
-CFLAGS0 = @CFLAGS@ -I@erl_interface_include@ @erl_interface_target_include@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@
+CFLAGS0 = @CFLAGS@ -I@erl_interface_include@
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@
EI_COMMON_OBJS = runner@obj@ ei_runner@obj@
ALL_OBJS = gccifier@exe@ $(EI_COMMON_OBJS)
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src
index 76dc84221f..10ef437f8b 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_ACCEPT_OBJS = ei_accept_test@obj@ ei_accept_test_decl@obj@
EIACCNODE_OBJS = eiaccnode@obj@
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src
index d1694e607d..c2d8261dd8 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_CONNECT_OBJS = ei_connect_test@obj@ ei_connect_test_decl@obj@
EINODE_OBJS = einode@obj@
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src
index 76591d893c..e678914a40 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_DECODE_OBJS = ei_decode_test@obj@ ei_decode_test_decl@obj@
all: ei_decode_test@exe@
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src
index 3f5fa4f295..853fe9ddeb 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_DECODE_ENCODE_OBJS = ei_decode_encode_test@obj@ ei_decode_encode_test_decl@obj@
all: ei_decode_encode_test@exe@
diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src
index 489382d85e..3b2cab7af4 100644
--- a/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_ENCODE_OBJS = ei_encode_test@obj@ ei_encode_test_decl@obj@
all: ei_encode_test@exe@
diff --git a/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src
index 9e5a271db6..b89dcae45a 100644
--- a/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_FORMAT_OBJS = ei_format_test@obj@ ei_format_test_decl@obj@
all: ei_format_test@exe@
diff --git a/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src
index 354011f1a5..150c11b99c 100644
--- a/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_PRINT_OBJS = ei_print_test@obj@ ei_print_test_decl@obj@
all: ei_print_test@exe@
diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src
index 76a9c6a606..b4ee361939 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \
$(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EI_TMO_OBJS = ei_tmo_test@obj@ ei_tmo_test_decl@obj@
all: ei_tmo_test@exe@
diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src
index 19b076794a..ff4c382c97 100644
--- a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
OBJS = erl_connect_test@obj@ erl_connect_test_decl@obj@
all: erl_connect_test@exe@
diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src
index cd4de56d7c..4b1ddf77b6 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @erl_interface_sock_libs@ @LIBS@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
ETERM_OBJS = eterm_test@obj@ eterm_test_decl@obj@
CNODE_OBJS = cnode@obj@
PRINT_OBJS = print_term@obj@
diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src
index 50b60637cd..fe8caebbd6 100644
--- a/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
EXT_OBJS = ext_test@obj@ ext_test_decl@obj@
all: ext_test@exe@
diff --git a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src
index 7d51cd6007..2ba59ab651 100644
--- a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
FORMAT_OBJS = format_test@obj@ format_test_decl@obj@
all: format_test@exe@
diff --git a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src
index 9f2a8619ac..1c1530d1b6 100644
--- a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
OBJS = erl_global_test@obj@ erl_global_test_decl@obj@
all: erl_global_test@exe@
diff --git a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src
index 56ed1df203..156214a269 100644
--- a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src
@@ -28,7 +28,7 @@ LIBEI = @erl_interface_eilib@
LIBFLAGS = ../all_SUITE_data/runner@obj@ \
$(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \
@erl_interface_threadlib@
-CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data
MATCH_OBJS = match_test@obj@ match_test_decl@obj@
all: match_test@exe@
diff --git a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
index e09e0fe175..0f97ce9f70 100644
--- a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
@@ -27,7 +27,7 @@ LIBERL = @erl_interface_lib_drv@
LIBEI = @erl_interface_eilib_drv@
SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI) @erl_interface_threadlib@
-SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ @erl_interface_target_include@ -I../all_SUITE_data
+SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ -I../all_SUITE_data
all: port_call_drv@dll@
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 06ef907d6c..0ed5c07bca 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.10.4
+EI_VSN = 3.11
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/ftp/doc/src/notes.xml b/lib/ftp/doc/src/notes.xml
index 01c1f88cf1..61da079900 100644
--- a/lib/ftp/doc/src/notes.xml
+++ b/lib/ftp/doc/src/notes.xml
@@ -33,7 +33,23 @@
<file>notes.xml</file>
</header>
- <section><title>Ftp 1.0.1</title>
+ <section><title>Ftp 1.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed timing related bug that could make ftp functions
+ behave badly.</p>
+ <p>
+ Own Id: OTP-15659 Aux Id: ERIERL-316 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ftp 1.0.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ftp/vsn.mk b/lib/ftp/vsn.mk
index d5d6c45b28..9f14658099 100644
--- a/lib/ftp/vsn.mk
+++ b/lib/ftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = ftp
-FTP_VSN = 1.0.1
+FTP_VSN = 1.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(FTP_VSN)$(PRE_VSN)"
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index e9cdf42018..9a803cb9df 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.18.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug in the handling of the <c>Key</c> argument
+ of <c>lists:{keysearch, keyfind, keymember}</c>. </p>
+ <p>
+ Own Id: OTP-15570</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.18.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 12d621bf01..39565d721f 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.18.2
+HIPE_VSN = 3.18.3
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 31dae6317e..91dd9cd6ed 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,43 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.0.5</title>
+ <section><title>Inets 7.0.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the internal handling of the option
+ erl_script_timeout in httpd. When httpd was started with
+ explicit erl_script_timeout, the value of the option was
+ converted to milliseconds before storage. Subsequent
+ calls to httpd:info/1 returned the input value multiplied
+ by 1000.</p>
+ <p>
+ This change fixes the handing of erl_script_timeout by
+ storing the timeout in seconds and converting to
+ milliseconds before usage.</p>
+ <p>
+ Own Id: OTP-15669 Aux Id: ERIERL-321 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Enhance documentation</p>
+ <p>
+ Own Id: OTP-15508 Aux Id: ERL-816 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 443b7ee564..f495f12f03 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -33,7 +33,7 @@
-include("httpd_internal.hrl").
-define(VMODULE,"ESI").
--define(DEFAULT_ERL_TIMEOUT,15000).
+-define(DEFAULT_ERL_TIMEOUT,15).
%%%=========================================================================
@@ -174,7 +174,7 @@ store({erl_script_alias, Value}, _) ->
{error, {wrong_type, {erl_script_alias, Value}}};
store({erl_script_timeout, TimeoutSec}, _)
when is_integer(TimeoutSec) andalso (TimeoutSec >= 0) ->
- {ok, {erl_script_timeout, TimeoutSec * 1000}};
+ {ok, {erl_script_timeout, TimeoutSec}};
store({erl_script_timeout, Value}, _) ->
{error, {wrong_type, {erl_script_timeout, Value}}};
store({erl_script_nocache, Value} = Conf, _)
@@ -500,7 +500,7 @@ kill_esi_delivery_process(Pid) ->
erl_script_timeout(Db) ->
- httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT).
+ httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT * 1000).
script_elements(FuncAndInput, Input) ->
case input_type(FuncAndInput) of
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 5b6740fba3..fcb9ad7905 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -78,7 +78,8 @@ all() ->
{group, http_rel_path_script_alias},
{group, http_not_sup},
{group, https_not_sup},
- mime_types_format
+ mime_types_format,
+ erl_script_timeout_option
].
groups() ->
@@ -1777,6 +1778,18 @@ mime_types_format(Config) when is_list(Config) ->
{"hqx","application/mac-binhex40"}]} = httpd_conf:load_mime_types(MimeTypes).
+erl_script_timeout_option(Config) when is_list(Config) ->
+ inets:start(),
+ {ok, Pid} = inets:start(httpd, [{erl_script_timeout, 215},
+ {server_name, "test"},
+ {port,0},
+ {server_root, "."},
+ {document_root, "."}]),
+ Info = httpd:info(Pid),
+ 215 = proplists:get_value(erl_script_timeout, Info),
+ inets:stop().
+
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 921161dce1..b7ddf39ebd 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 7.0.5
+INETS_VSN = 7.0.6
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 5170502581..83a83ebad2 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -238,8 +238,8 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="set_env" arity="1" since="OTP @OTP-15642@"/>
- <name name="set_env" arity="2" since="OTP @OTP-15642@"/>
+ <name name="set_env" arity="1" since="OTP 21.3"/>
+ <name name="set_env" arity="2" since="OTP 21.3"/>
<fsummary>Sets the configuration parameters of multiple applications.</fsummary>
<desc>
<p>Sets the configuration <c><anno>Config</anno></c> for multiple
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index ebebcaa1ae..2a060ce1f9 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -1119,7 +1119,7 @@ logger:set_proxy_config(maps:merge(Old, Config)).
</func>
<func>
- <name name="timestamp" arity="0" since="OTP @OTP-15625@"/>
+ <name name="timestamp" arity="0" since="OTP 21.3"/>
<fsummary>Return a timestamp to insert in meta data for a log
event.</fsummary>
<desc>
@@ -1351,5 +1351,3 @@ logger:set_proxy_config(maps:merge(Old, Config)).
</p>
</section>
</erlref>
-
-
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 1f4d9be1f5..0c187eb19f 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -31,6 +31,185 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If for example the <c>/etc/hosts</c> did not come into
+ existence until after the kernel application had started,
+ its content was never read. This bug has now been
+ corrected.</p>
+ <p>
+ Own Id: OTP-14702 Aux Id: PR-2066 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where doing <c>seq_trace:reset_trace()</c> while
+ another process was doing a garbage collection could
+ cause the run-time system to segfault.</p>
+ <p>
+ Own Id: OTP-15490</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>erl_epmd:port_please</c> spec to include
+ <c>atom()</c> and <c>string()</c>.</p>
+ <p>
+ Own Id: OTP-15557 Aux Id: PR-2117 </p>
+ </item>
+ <item>
+ <p>
+ The Logger handler logger_std_h now keeps track of the
+ inode of its log file in order to re-open the file if the
+ inode changes. This may happen, for instance, if the log
+ file is opened and saved by an editor.</p>
+ <p>
+ Own Id: OTP-15578 Aux Id: ERL-850 </p>
+ </item>
+ <item>
+ <p>
+ When user specific file modes are given to the logger
+ handler <c>logger_std_h</c>, they were earlier accepted
+ without any control. This is now changes, so Logger will
+ adjust the file modes as follows:</p>
+ <p>
+ - If <c>raw</c> is not found in the list, it is
+ added.<br/> - If none of <c>write</c>, <c>append</c> or
+ <c>exclusive</c> are found in the list, <c>append</c> is
+ added.<br/> - If none of <c>delayed_write</c> or
+ <c>{delayed_write,Size,Delay}</c> are found in the list,
+ <c>delayed_write</c> is added.</p>
+ <p>
+ Own Id: OTP-15602</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The standard logger handler, <c>logger_std_h</c>, now has
+ a new internal feature for log rotation. The rotation
+ scheme is as follows:</p>
+ <p>
+ The log file to which the handler currently writes always
+ has the same name, i.e. the name which is configured for
+ the handler. The archived files have the same name, but
+ with extension ".N", where N is an integer. The newest
+ archive has extension ".0", and the oldest archive has
+ the highest number. </p>
+ <p>
+ The size at which the log file is rotated, and the number
+ of archive files that are kept, is specified with the
+ handler specific configuration parameters
+ <c>max_no_bytes</c> and <c>max_no_files</c> respectively. </p>
+ <p>
+ Archives can be compressed, in which case they get a
+ ".gz" file extension after the integer. Compression is
+ specified with the handler specific configuration
+ parameter <c>compress_on_rotate</c>.</p>
+ <p>
+ Own Id: OTP-15479</p>
+ </item>
+ <item>
+ <p>
+ The new functions <c>logger:i/0</c> and <c>logger:i/1</c>
+ are added. These provide the same information as
+ <c>logger:get_config/0</c> and other
+ <c>logger:get_*_config</c> functions, but the information
+ is more logically sorted and more readable.</p>
+ <p>
+ Own Id: OTP-15600</p>
+ </item>
+ <item>
+ <p>
+ Logger is now protected against overload due to massive
+ amounts of log events from the emulator or from remote
+ nodes.</p>
+ <p>
+ Own Id: OTP-15601</p>
+ </item>
+ <item>
+ <p>
+ Logger now uses os:system_time/1 instead of
+ erlang:system_time/1 to generate log event timestamps.</p>
+ <p>
+ Own Id: OTP-15625</p>
+ </item>
+ <item>
+ <p>
+ Add functions <c>application:set_env/1,2</c> and
+ <c>application:set_env/2</c>. These take a list of
+ application configuration parameters, and the behaviour
+ is equivalent to calling <c>application:set_env/4</c>
+ individually for each application/key combination, except
+ it is more efficient.</p>
+ <p>
+ <c>set_env/1,2</c> warns about duplicated applications or
+ keys. The warning is also emitted during boot, if
+ applications or keys are duplicated within one
+ configuration file, e.g. sys.config.</p>
+ <p>
+ Own Id: OTP-15642 Aux Id: PR-2164 </p>
+ </item>
+ <item>
+ <p>
+ Handler specific configuration parameters for the
+ standard handler <c>logger_std_h</c> are changed to be
+ more intuitive and more similar to the disk_log handler.</p>
+ <p>
+ Earlier there was only one parameter, <c>type</c>, which
+ could have the values <c>standard_io</c>,
+ <c>standard_error</c>, <c>{file,FileName}</c> or
+ <c>{file,FileName,Modes}</c>.</p>
+ <p>
+ This is now changed, so the following parameters are
+ allowed:</p>
+ <p>
+ <c>type = standard_io | standard_error | file</c><br/>
+ <c>file = file:filename()</c><br/> <c>modes =
+ [file:mode()]</c></p>
+ <p>
+ All parameters are optional. <c>type</c> defaults to
+ <c>standard_io</c>, unless a file name is given, in which
+ case it defaults to <c>file</c>. If <c>type</c> is set to
+ <c>file</c>, the file name defaults to the same as the
+ handler id.</p>
+ <p>
+ The potential incompatibility is that
+ <c>logger:get_config/0</c> and
+ <c>logger:get_handler_config/1</c> now returns the new
+ parameters, even if the configuration was set with the
+ old variant, e.g. <c>#{type=>{file,FileName}}</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15662</p>
+ </item>
+ <item>
+ <p>
+ The new configuration parameter <c>file_check</c> is
+ added to the Logger handler <c>logger_std_h</c>. This
+ parameter specifies how long (in milliseconds) the
+ handler may wait before checking if the log file still
+ exists and the inode is the same as when it was opened.</p>
+ <p>
+ The default value is 0, which means that this check is
+ done prior to each write operation. Setting a higher
+ number may improve performance, but adds the risk of
+ loosing log events.</p>
+ <p>
+ Own Id: OTP-15663</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 6.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 66fbcbf78d..8fa3f5c588 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -42,7 +42,8 @@
{<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^6\\.2$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
[{<<"^5\\.3$">>,[restart_new_emulator]},
{<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -58,4 +59,5 @@
{<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^6\\.2$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
+ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 6e0eea7824..7bebe1ba70 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 6.2.1
+KERNEL_VSN = 6.3
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 8fc3610bb6..01d1666b8d 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -39,7 +39,22 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.15.5</title>
+ <section><title>Mnesia 4.15.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Avoid overload warnings caused by a race condition.</p>
+ <p>
+ Own Id: OTP-15619 Aux Id: ERIERL-310 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 1cfb35c774..781a4830a0 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.15.5
+MNESIA_VSN = 4.15.6
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 22035af982..2d914f8c61 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -32,6 +32,45 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Since Logger was introduced in OTP-21.0, menu choice
+ <em>Log &gt; Toggle Log View</em> in observer would cause
+ a crash unless an <c>error_logger</c> event handler was
+ explicitly installed. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15553 Aux Id: ERL-848 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Since persistent_term was introduced, observer would
+ sometimes crash when expanding a term from a process
+ state. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15493 Aux Id: ERL-810 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>OBSERVER_SCALE</c> environment variable for HiDPI
+ support.</p>
+ <p>
+ Own Id: OTP-15586 Aux Id: PR-2105 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.8.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 5ce0aca589..0e9c8b302c 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.8.2
+OBSERVER_VSN = 2.9
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index dba7663bb9..696fcaa479 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -32,7 +32,22 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.12.2</title>
+ <section><title>ODBC 2.12.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling to avoid stack corruption</p>
+ <p>
+ Own Id: OTP-15667 Aux Id: ERL-808, PR-2065 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index bb21016fad..ff023e666b 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.12.2
+ODBC_VSN = 2.12.3
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index b3e6023c41..f6bc0dc797 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -35,6 +35,21 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.6.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add export of dialyzer type</p>
+ <p>
+ Own Id: OTP-15624</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.6.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 5e2643f0ea..11c06fb158 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.6.4
+PUBLIC_KEY_VSN = 1.6.5
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 810bb8207c..58a2a66c4b 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.13.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update of systemtap trace example scripts.</p>
+ <p>
+ Own Id: OTP-15670</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.13.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index aa3d702997..fa2f338ec2 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.13.1
+RUNTIME_TOOLS_VSN = 1.13.2
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 0bc4baf5eb..17f14bdea2 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -30,6 +30,23 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SSH sftp daemon now accepts an SSH_FXP_STAT message
+ encoded according to the wrong sftp version. Some clients
+ sends such messages.</p>
+ <p>
+ Own Id: OTP-15498 Aux Id: ERL-822, PR-2077 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.7.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 2890d7fe5b..0f9eee887c 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,4 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.7.3
+SSH_VSN = 4.7.4
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 82eb8ff700..732fdc71e7 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,93 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug that an incorrect return value for gen_statem
+ could be created when alert was a result of handling
+ renegotiation info extension</p>
+ <p>
+ Own Id: OTP-15502</p>
+ </item>
+ <item>
+ <p>
+ Correct check for 3des_ede_cbc, could cause ssl to claim
+ to support 3des_ede_cbc when cryptolib does not.</p>
+ <p>
+ Own Id: OTP-15539</p>
+ </item>
+ <item>
+ <p>
+ Improved DTLS error handling, avoids unexpected
+ connection failure in rare cases.</p>
+ <p>
+ Own Id: OTP-15561</p>
+ </item>
+ <item>
+ <p>
+ Corrected active once emulation bug that could cause the
+ ssl_closed meassage to not be sent. Bug introduced by
+ OTP-15449</p>
+ <p>
+ Own Id: OTP-15666 Aux Id: ERIERL-316, </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add client option {reuse_session, SessionID::binary()}
+ that can be used together with new option value
+ {reuse_sessions, save}. This makes it possible to reuse a
+ session from a specific connection establishment.</p>
+ <p>
+ Own Id: OTP-15369</p>
+ </item>
+ <item>
+ <p>
+ The Reason part of of the error return from the functions
+ connect and handshake has a better and documented format.
+ This will sometimes differ from previous returned
+ reasons, however those where only documented as term()
+ and should for that reason not be relied on.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15423</p>
+ </item>
+ <item>
+ <p>
+ Refactor of state handling to improve TLS application
+ data throughput and reduce CPU overhead</p>
+ <p>
+ Own Id: OTP-15445</p>
+ </item>
+ <item>
+ <p>
+ The SSL code has been optimized in many small ways to
+ reduce CPU load for encryption/decryption, especially for
+ Erlang's distribution protocol over TLS.</p>
+ <p>
+ Own Id: OTP-15529</p>
+ </item>
+ <item>
+ <p>
+ Add support for active N</p>
+ <p>
+ Own Id: OTP-15665 Aux Id: ERL-811, PR-2072 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 9.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 3527062a8a..0d9f907d5c 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 9.1.2
+SSL_VSN = 9.2
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index dee7136eb1..23c3f6e981 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,57 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug in the Erlang Pretty Printer: long atom
+ names in combination with <c>&lt;&lt;&gt;&gt;</c> could
+ cause a crash. </p>
+ <p>
+ Own Id: OTP-15592 Aux Id: ERL-818 </p>
+ </item>
+ <item>
+ <p> Fix bugs that could cause wrong results or bad
+ performance when formatting lists of characters using the
+ control sequences <c>p</c> or <c>P</c> and limiting the
+ output with the option <c>chars_limit</c>. </p>
+ <p>
+ Own Id: OTP-15639</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improved ETS documentation about safe table traversal and
+ the partially bound key optimization for
+ <c>ordered_set</c>.</p>
+ <p>
+ Own Id: OTP-15545 Aux Id: PR-2103, PR-2139 </p>
+ </item>
+ <item>
+ <p> Optimize <c>calendar:gregorian_days_to_date/1</c>.
+ </p>
+ <p>
+ Own Id: OTP-15572 Aux Id: PR-2121 </p>
+ </item>
+ <item>
+ <p> Optimize functions
+ <c>calendar:rfc3339_to_system_time()</c> and
+ <c>calendar:system_time_to_rfc3339()</c>. </p>
+ <p>
+ Own Id: OTP-15630</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 9e5d6a3bd8..37ea97c353 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -40,7 +40,8 @@
{<<"^3\\.6$">>,[restart_new_emulator]},
{<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.7$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
[{<<"^3\\.4$">>,[restart_new_emulator]},
{<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -54,4 +55,5 @@
{<<"^3\\.6$">>,[restart_new_emulator]},
{<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.7$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
+ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index d46173497b..cbefd6590a 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.7.1
+STDLIB_VSN = 3.8
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index dc13fe474b..772f5e6e04 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -32,6 +32,20 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 2.1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix pretty-printing of type funs. </p>
+ <p>
+ Own Id: OTP-15519 Aux Id: ERL-815 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 8959ebbd04..538c71dc24 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.6
+SYNTAX_TOOLS_VSN = 2.1.7
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index a6781dfdb3..28f8346a19 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -31,6 +31,45 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Minor fixes for <c>make clean</c>.</p>
+ <p>
+ Own Id: OTP-15657</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ In the HTML file generated by
+ <c>cover:analyse_to_file/1,2</c>, a link is now added to
+ the line number. This makes it easier to share pointers
+ to specific lines.</p>
+ <p>
+ Own Id: OTP-15541</p>
+ </item>
+ <item>
+ <p>
+ Uncovered lines are now marked with a sad face,
+ <c>:-(</c>, in the HTML output from
+ <c>cover:analyse_to_file/1,2</c>. This is to make these
+ lines easier to find by search.</p>
+ <p>
+ Own Id: OTP-15542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 3.0.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index bb8305e9f1..5700885549 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 3.0.2
+TOOLS_VSN = 3.1
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 1061e73138..33d02e22ba 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -32,6 +32,25 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 1.8.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved support for wxWidgets 3.1.3 which have changed
+ <c>wxFONTWEIGTH</c>, also added <c>wxGCDC</c> and
+ <c>wxDisplay</c> modules.</p>
+ <p>
+ Fixed a crash on Mojave and check for events more often.</p>
+ <p>
+ Own Id: OTP-15587</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 1.8.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index d241a7a1b4..dac219fa98 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 1.8.6
+WX_VSN = 1.8.7
diff --git a/make/otp_version_tickets_in_merge b/make/otp_version_tickets_in_merge
index e69de29bb2..77633c2ce2 100644
--- a/make/otp_version_tickets_in_merge
+++ b/make/otp_version_tickets_in_merge
@@ -0,0 +1,79 @@
+OTP-14702
+OTP-15229
+OTP-15298
+OTP-15369
+OTP-15375
+OTP-15398
+OTP-15423
+OTP-15442
+OTP-15445
+OTP-15447
+OTP-15460
+OTP-15479
+OTP-15484
+OTP-15490
+OTP-15493
+OTP-15494
+OTP-15498
+OTP-15502
+OTP-15503
+OTP-15508
+OTP-15514
+OTP-15518
+OTP-15519
+OTP-15527
+OTP-15529
+OTP-15539
+OTP-15540
+OTP-15541
+OTP-15542
+OTP-15545
+OTP-15552
+OTP-15553
+OTP-15555
+OTP-15556
+OTP-15557
+OTP-15558
+OTP-15561
+OTP-15562
+OTP-15567
+OTP-15569
+OTP-15570
+OTP-15572
+OTP-15576
+OTP-15577
+OTP-15578
+OTP-15580
+OTP-15583
+OTP-15584
+OTP-15586
+OTP-15587
+OTP-15592
+OTP-15599
+OTP-15600
+OTP-15601
+OTP-15602
+OTP-15604
+OTP-15605
+OTP-15619
+OTP-15624
+OTP-15625
+OTP-15629
+OTP-15630
+OTP-15634
+OTP-15637
+OTP-15639
+OTP-15642
+OTP-15647
+OTP-15650
+OTP-15654
+OTP-15657
+OTP-15659
+OTP-15660
+OTP-15662
+OTP-15663
+OTP-15665
+OTP-15666
+OTP-15667
+OTP-15669
+OTP-15670
diff --git a/otp_versions.table b/otp_versions.table
index 0f79284903..eef6a9c8fe 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,4 @@
+OTP-21.3 : common_test-1.17 compiler-7.3.2 crypto-4.4.1 dialyzer-3.3.2 diameter-2.2 edoc-0.10 erl_docgen-0.9 erl_interface-3.11 erts-10.3 ftp-1.0.2 hipe-3.18.3 inets-7.0.6 kernel-6.3 mnesia-4.15.6 observer-2.9 odbc-2.12.3 public_key-1.6.5 runtime_tools-1.13.2 ssh-4.7.4 ssl-9.2 stdlib-3.8 syntax_tools-2.1.7 tools-3.1 wx-1.8.7 # asn1-5.0.8 debugger-4.2.6 eldap-1.2.6 et-1.6.4 eunit-2.3.7 jinterface-1.9.1 megaco-3.18.4 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 reltool-0.7.8 sasl-3.3 snmp-5.2.12 tftp-1.0.1 xmerl-1.3.19 :
OTP-21.2.7 : erts-10.2.5 kernel-6.2.1 # asn1-5.0.8 common_test-1.16.1 compiler-7.3.1 crypto-4.4 debugger-4.2.6 dialyzer-3.3.1 diameter-2.1.6 edoc-0.9.4 eldap-1.2.6 erl_docgen-0.8.1 erl_interface-3.10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.1 hipe-3.18.2 inets-7.0.5 jinterface-1.9.1 megaco-3.18.4 mnesia-4.15.5 observer-2.8.2 odbc-2.12.2 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.4 reltool-0.7.8 runtime_tools-1.13.1 sasl-3.3 snmp-5.2.12 ssh-4.7.3 ssl-9.1.2 stdlib-3.7.1 syntax_tools-2.1.6 tftp-1.0.1 tools-3.0.2 wx-1.8.6 xmerl-1.3.19 :
OTP-21.2.6 : erts-10.2.4 stdlib-3.7.1 # asn1-5.0.8 common_test-1.16.1 compiler-7.3.1 crypto-4.4 debugger-4.2.6 dialyzer-3.3.1 diameter-2.1.6 edoc-0.9.4 eldap-1.2.6 erl_docgen-0.8.1 erl_interface-3.10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.1 hipe-3.18.2 inets-7.0.5 jinterface-1.9.1 kernel-6.2 megaco-3.18.4 mnesia-4.15.5 observer-2.8.2 odbc-2.12.2 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.4 reltool-0.7.8 runtime_tools-1.13.1 sasl-3.3 snmp-5.2.12 ssh-4.7.3 ssl-9.1.2 syntax_tools-2.1.6 tftp-1.0.1 tools-3.0.2 wx-1.8.6 xmerl-1.3.19 :
OTP-21.2.5 : inets-7.0.5 # asn1-5.0.8 common_test-1.16.1 compiler-7.3.1 crypto-4.4 debugger-4.2.6 dialyzer-3.3.1 diameter-2.1.6 edoc-0.9.4 eldap-1.2.6 erl_docgen-0.8.1 erl_interface-3.10.4 erts-10.2.3 et-1.6.4 eunit-2.3.7 ftp-1.0.1 hipe-3.18.2 jinterface-1.9.1 kernel-6.2 megaco-3.18.4 mnesia-4.15.5 observer-2.8.2 odbc-2.12.2 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.4 reltool-0.7.8 runtime_tools-1.13.1 sasl-3.3 snmp-5.2.12 ssh-4.7.3 ssl-9.1.2 stdlib-3.7 syntax_tools-2.1.6 tftp-1.0.1 tools-3.0.2 wx-1.8.6 xmerl-1.3.19 :