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/alt_dist.xml2
-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/bif.c6
-rw-r--r--erts/emulator/beam/bif_instrs.tab114
-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/beam/ops.tab30
-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/emulator/test/trace_local_SUITE.erl4
-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/beam_except_SUITE.erl13
-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
106 files changed, 3047 insertions, 2047 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/alt_dist.xml b/erts/doc/src/alt_dist.xml
index e6245130fc..7c997cae20 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -60,7 +60,7 @@
parts of the logic in Erlang code, and you perhaps do not
even need a new driver for the protocol. One example could
be Erlang distribution over UDP using <c>gen_udp</c> (your
- Erlang code will of course have to take care of retranspissions,
+ Erlang code will of course have to take care of retransmissions,
etc in this example). That is, depending on what you want
to do you perhaps do not need to implement a driver at all
and can then skip the driver related sections below.
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/bif.c b/erts/emulator/beam/bif.c
index 7faba35e1c..c102ddbee6 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -5165,6 +5165,12 @@ erts_schedule_bif(Process *proc,
pc = i;
mfa = &exp->info.mfa;
}
+ else if (BeamIsOpCode(*i, op_call_bif_only_e)) {
+ /* Pointer to bif export in i+1 */
+ exp = (Export *) i[1];
+ pc = i;
+ mfa = &exp->info.mfa;
+ }
else if (BeamIsOpCode(*i, op_apply_bif)) {
/* Pointer to bif in i+1, and mfa in i-3 */
pc = c_p->cp;
diff --git a/erts/emulator/beam/bif_instrs.tab b/erts/emulator/beam/bif_instrs.tab
index 8499f61114..8e0caa38a3 100644
--- a/erts/emulator/beam/bif_instrs.tab
+++ b/erts/emulator/beam/bif_instrs.tab
@@ -209,8 +209,8 @@ i_length.execute(Fail, Live, Dst) {
}
//
-// The most general BIF call. The BIF may build any amount of data
-// on the heap. The result is always returned in r(0).
+// Call a BIF, store the result in x(0) and transfer control to the
+// next instruction.
//
call_bif(Exp) {
ErtsBifFunc bf;
@@ -219,8 +219,10 @@ call_bif(Exp) {
Export *export = (Export*) $Exp;
if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) {
- /* If we have run out of reductions, we do a context
- switch before calling the bif */
+ /*
+ * If we have run out of reductions, do a context
+ * switch before calling the BIF.
+ */
c_p->arity = GET_BIF_ARITY(export);
c_p->current = &export->info.mfa;
goto context_switch3;
@@ -257,9 +259,12 @@ call_bif(Exp) {
HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
ERTS_DBG_CHK_REDS(c_p, FCALLS);
- /* We have to update the cache if we are enabled in order
- to make sure no book keeping is done after we disabled
- msacc. We don't always do this as it is quite expensive. */
+
+ /*
+ * We have to update the cache if we are enabled in order
+ * to make sure no bookkeeping is done after we disabled
+ * msacc. We don't always do this as it is quite expensive.
+ */
if (ERTS_MSACC_IS_ENABLED_CACHED_X()) {
ERTS_MSACC_UPDATE_CACHE_X();
}
@@ -269,6 +274,12 @@ call_bif(Exp) {
CHECK_TERM(r(0));
$NEXT0();
} else if (c_p->freason == TRAP) {
+ /*
+ * Set the continuation pointer to return to next
+ * instruction after the trap (either by a return from
+ * erlang code or by nif_bif.epilogue() when the BIF
+ * is done).
+ */
SET_CP(c_p, $NEXT_INSTRUCTION);
SET_I(c_p->i);
SWAPIN;
@@ -281,6 +292,95 @@ call_bif(Exp) {
ASSERT(c_p->stop == E);
I = handle_error(c_p, I, reg, &export->info.mfa);
goto post_error_handling;
+ //| -no_next
+}
+
+//
+// Call a BIF tail-recursively, storing the result in x(0) and doing
+// a return to the continuation poiner (c_p->cp).
+//
+
+call_bif_only(Exp) {
+ ErtsBifFunc bf;
+ Eterm result;
+ ErlHeapFragment *live_hf_end;
+ Export *export = (Export*) $Exp;
+
+ if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) {
+ /*
+ * If we have run out of reductions, do a context
+ * switch before calling the BIF.
+ */
+ c_p->arity = GET_BIF_ARITY(export);
+ c_p->current = &export->info.mfa;
+ goto context_switch3;
+ }
+
+ ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_BIF_MODULE(export),
+ GET_BIF_ADDRESS(export));
+
+ bf = GET_BIF_ADDRESS(export);
+
+ PRE_BIF_SWAPOUT(c_p);
+ ERTS_DBG_CHK_REDS(c_p, FCALLS);
+ c_p->fcalls = FCALLS - 1;
+ if (FCALLS <= 0) {
+ save_calls(c_p, export);
+ }
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ live_hf_end = c_p->mbuf;
+ ERTS_CHK_MBUF_SZ(c_p);
+ result = (*bf)(c_p, reg, I);
+ ERTS_CHK_MBUF_SZ(c_p);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_HOLE_CHECK(c_p);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ if (ERTS_IS_GC_DESIRED(c_p)) {
+ Uint arity = GET_BIF_ARITY(export);
+ result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result,
+ reg, arity);
+ E = c_p->stop;
+ }
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ HTOP = HEAP_TOP(c_p);
+ FCALLS = c_p->fcalls;
+ ERTS_DBG_CHK_REDS(c_p, FCALLS);
+
+ /*
+ * We have to update the cache if we are enabled in order
+ * to make sure no bookkeeping is done after we disabled
+ * msacc. We don't always do this as it is quite expensive.
+ */
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X()) {
+ ERTS_MSACC_UPDATE_CACHE_X();
+ }
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR);
+ if (ERTS_LIKELY(is_value(result))) {
+ /*
+ * Success. Store the result and return to the caller.
+ */
+ r(0) = result;
+ CHECK_TERM(r(0));
+ $return();
+ } else if (c_p->freason == TRAP) {
+ /*
+ * Dispatch to a trap. When the trap is done, a jump
+ * to the continuation pointer (c_p->cp) will be done.
+ */
+ SET_I(c_p->i);
+ SWAPIN;
+ Dispatch();
+ }
+
+ /*
+ * Error handling. SWAPOUT is not needed because it was done above.
+ */
+ ASSERT(c_p->stop == E);
+ I = handle_error(c_p, I, reg, &export->info.mfa);
+ goto post_error_handling;
+ //| -no_next
}
//
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/beam/ops.tab b/erts/emulator/beam/ops.tab
index e688c6996b..da5364183c 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -74,23 +74,19 @@ trace_jump W
return
+# To ensure that a "move Src x(0)" instruction can be combined with
+# the following call instruction, we need to make sure that there is
+# no line/1 instruction between the move and the call.
#
-# To ensure that a "move Src x(0)" instruction can be combined
-# with the following call instruction, we need to make sure that
-# there is no line/1 instruction between the move and the call.
-#
-# A tail-recursive call to an external function (non-BIF) will
-# never be saved on the stack, so there is no reason to keep
-# the line instruction. (The compiler did not remove the line
-# instruction because it cannot tell the difference between
-# BIFs and ordinary Erlang functions.)
-#
+# A tail-recursive call to an external function (BIF or non-BIF) will
+# never be saved on the stack, so there is no reason to keep the line
+# instruction.
move S X0=x==0 | line Loc | call_ext Ar Func => \
line Loc | move S X0 | call_ext Ar Func
-move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+move S X0=x==0 | line Loc | call_ext_last Ar Func D => \
move S X0 | call_ext_last Ar Func D
-move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif => \
+move S X0=x==0 | line Loc | call_ext_only Ar Func => \
move S X0 | call_ext_only Ar Func
move S X0=x==0 | line Loc | call Ar Func => \
line Loc | move S X0 | call Ar Func
@@ -102,9 +98,9 @@ line I
allocate t t?
allocate_heap t I t?
-%cold
+# This instruction when a BIF is called tail-recursively when
+# ther is stack frame.
deallocate Q
-%hot
init y
allocate_zero t t?
@@ -985,10 +981,9 @@ call_ext_only u==0 u$func:os:perf_counter/0 => \
call_ext u Bif=u$is_bif => call_bif Bif
-call_ext_last u Bif=u$is_bif D => call_bif Bif | deallocate_return D
+call_ext_last u Bif=u$is_bif D => deallocate D | call_bif_only Bif
-call_ext_only Ar=u Bif=u$is_bif => \
- allocate u Ar | call_bif Bif | deallocate_return u
+call_ext_only Ar=u Bif=u$is_bif => call_bif_only Bif
#
# Any remaining calls are calls to Erlang functions, not BIFs.
@@ -1020,6 +1015,7 @@ i_perf_counter
%hot
call_bif e
+call_bif_only e
#
# Calls to non-building and guard BIFs.
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/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index 253d5fed23..ad802352b9 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -1181,7 +1181,9 @@ undef(X) ->
?MODULE:undef(X, X). % undef
lists_reverse(A, B) ->
- lists:reverse(A, B).
+ Res = lists:reverse(A, B),
+ _ = (catch abs(A)),
+ Res.
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/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 9380fe06c8..8e3b373d29 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -84,9 +84,16 @@ coverage(_) ->
{'EXIT',{function_clause,
[{?MODULE,fc,[y],[File,{line,2}]}|_]}} =
(catch fc(y)),
- {'EXIT',{function_clause,
- [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} =
- (catch fc([a,b,c])),
+ case ?MODULE of
+ beam_except_no_opt_SUITE ->
+ %% There will be a different stack fram in
+ %% unoptimized code.
+ ok;
+ _ ->
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} =
+ (catch fc([a,b,c]))
+ end,
{'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} =
(catch erlang:error(a, b, c)),
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 :