aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin14340 -> 14424 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bool.beambin16256 -> 16480 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dead.beambin10176 -> 10212 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin5740 -> 5360 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin8408 -> 8524 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin13108 -> 13220 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin35644 -> 37548 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin5344 -> 5460 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin10896 -> 12064 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin46668 -> 47060 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin4168 -> 4208 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin50652 -> 51060 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin43392 -> 43196 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin10596 -> 11780 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin26148 -> 26184 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32136 -> 32324 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin11720 -> 13576 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp_dist.beambin6208 -> 6248 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin25956 -> 26408 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin12776 -> 12936 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin6496 -> 6532 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin22712 -> 22756 bytes
-rw-r--r--bootstrap/lib/kernel/include/file.hrl59
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin53412 -> 53452 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin28736 -> 28820 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6348 -> 6796 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin.beambin7912 -> 9260 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin27204 -> 27164 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin82112 -> 82592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin69912 -> 69040 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin23800 -> 24544 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin31120 -> 33120 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin15228 -> 15328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin21660 -> 21688 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin17520 -> 17560 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin15136 -> 15360 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin16896 -> 17264 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin29524 -> 29556 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3816 -> 3848 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin70944 -> 71084 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/queue.beambin5900 -> 6184 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin40500 -> 40756 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin7292 -> 7332 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin10928 -> 11584 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin25212 -> 26740 bytes
-rw-r--r--erts/configure.in6
-rw-r--r--erts/doc/src/absform.xml7
-rw-r--r--erts/doc/src/erl.xml37
-rw-r--r--erts/doc/src/erl_driver.xml6
-rw-r--r--erts/doc/src/erlang.xml16
-rw-r--r--erts/emulator/beam/bif.h2
-rw-r--r--erts/emulator/beam/erl_cpu_topology.c38
-rw-r--r--erts/emulator/beam/erl_cpu_topology.h2
-rw-r--r--erts/emulator/beam/erl_init.c30
-rw-r--r--erts/emulator/beam/erl_port.h39
-rw-r--r--erts/emulator/beam/erl_port_task.c10
-rw-r--r--erts/emulator/beam/erl_process.c16
-rw-r--r--erts/emulator/beam/io.c27
-rw-r--r--erts/emulator/drivers/common/efile_drv.c93
-rw-r--r--erts/emulator/drivers/common/inet_drv.c66
-rw-r--r--erts/emulator/drivers/win32/win_efile.c10
-rw-r--r--erts/emulator/hipe/hipe_x86_gc.h2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c10
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl304
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c4
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/scheduling_drv.c190
-rw-r--r--erts/emulator/test/driver_SUITE_data/async_blast_drv.c8
-rw-r--r--erts/emulator/test/driver_SUITE_data/caller_drv.c4
-rw-r--r--erts/emulator/test/driver_SUITE_data/monitor_drv.c2
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_9302_drv.c4
-rw-r--r--erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c11
-rw-r--r--erts/emulator/test/driver_SUITE_data/thr_msg_blast_drv.c4
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c10
-rw-r--r--erts/emulator/test/send_term_SUITE_data/send_term_drv.c8
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl2
-rw-r--r--erts/etc/common/erlexec.c1
-rw-r--r--erts/preloaded/ebin/erlang.beambin92756 -> 92840 bytes
-rw-r--r--erts/preloaded/src/erlang.erl2
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl3
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE.erl5
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_test_support.erl4
-rw-r--r--lib/compiler/src/beam_dict.erl18
-rw-r--r--lib/compiler/src/sys_core_fold.erl37
-rw-r--r--lib/compiler/src/v3_kernel.erl31
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl48
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl27
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl4
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/empty_list_infimum2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/empty_list_infimum.erl57
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/unknown_arity_function_spec.erl10
-rw-r--r--lib/eldap/doc/src/eldap.xml2
-rw-r--r--lib/eldap/src/eldap.erl11
-rw-r--r--lib/erl_docgen/priv/dtd/common.refs.dtd7
-rw-r--r--lib/erl_docgen/priv/dtd/erlref.dtd3
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl12
-rw-r--r--lib/erl_docgen/vsn.mk3
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl5
-rw-r--r--lib/hipe/cerl/erl_types.erl4
-rw-r--r--lib/kernel/doc/src/file.xml53
-rw-r--r--lib/kernel/include/file.hrl59
-rw-r--r--lib/kernel/src/group.erl140
-rw-r--r--lib/kernel/test/file_SUITE.erl57
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl82
-rw-r--r--lib/megaco/doc/src/definitions/term.defs1
-rw-r--r--lib/megaco/doc/src/definitions/term.defs.xml7
-rw-r--r--lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src10
-rw-r--r--lib/mnesia/include/mnemosyne.hrl18
-rw-r--r--lib/mnesia/src/mnesia.erl2
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl4
-rw-r--r--lib/mnesia/src/mnesia_sup.erl13
-rw-r--r--lib/mnesia/test/mnesia.spec3
-rw-r--r--lib/mnesia/test/mnesia_SUITE.erl1
-rw-r--r--lib/mnesia/test/mnesia_config_test.erl42
-rw-r--r--lib/mnesia/test/mnesia_measure_test.erl3
-rw-r--r--lib/orber/src/orber_ifr_exceptiondef.erl20
-rw-r--r--lib/parsetools/test/leex_SUITE.erl1
-rw-r--r--lib/public_key/src/public_key.erl4
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/snmp/doc/src/notes.xml146
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl6
-rw-r--r--lib/snmp/src/app/snmp.appup.src574
-rw-r--r--lib/snmp/src/manager/snmpm_server.erl37
-rw-r--r--lib/snmp/src/manager/snmpm_user_default.erl6
-rw-r--r--lib/ssh/src/ssh.appup.src2
-rw-r--r--lib/ssh/src/ssh.erl48
-rw-r--r--lib/ssh/src/ssh_client_key_api.erl2
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl14
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml1284
-rw-r--r--lib/ssl/src/ssl.appup.src15
-rw-r--r--lib/ssl/src/ssl_alert.erl11
-rw-r--r--lib/ssl/src/ssl_connection.erl122
-rw-r--r--lib/ssl/src/ssl_handshake.erl188
-rw-r--r--lib/ssl/src/ssl_handshake.hrl9
-rw-r--r--lib/ssl/src/ssl_manager.erl43
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl55
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl44
-rw-r--r--lib/ssl/test/ssl_test_lib.erl77
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl2
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl5
-rw-r--r--lib/stdlib/src/base64.erl4
-rw-r--r--lib/stdlib/src/edlin.erl109
-rw-r--r--lib/stdlib/src/epp.erl2
-rw-r--r--lib/stdlib/src/erl_lint.erl4
-rw-r--r--lib/stdlib/src/erl_parse.yrl8
-rw-r--r--lib/stdlib/src/erl_pp.erl2
-rw-r--r--lib/stdlib/src/erl_scan.erl1
-rw-r--r--lib/stdlib/src/queue.erl14
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl22
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl2
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl7
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl55
-rw-r--r--lib/test_server/src/ts_lib.erl1
-rw-r--r--lib/tools/src/cover.erl6
-rw-r--r--lib/tools/src/xref_reader.erl9
-rw-r--r--lib/tools/test/cprof_SUITE.erl16
-rw-r--r--lib/tv/src/tv_main.hrl1
-rw-r--r--lib/wx/examples/demo/demo_html_tagger.erl1
-rwxr-xr-xmake/fakefop118
-rw-r--r--make/otp.mk.in1
-rw-r--r--make/otp_release_targets.mk3
167 files changed, 2082 insertions, 2879 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 7c287dc773..72cce89b9d 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bool.beam b/bootstrap/lib/compiler/ebin/beam_bool.beam
index 0324c7743f..18eb174687 100644
--- a/bootstrap/lib/compiler/ebin/beam_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dead.beam b/bootstrap/lib/compiler/ebin/beam_dead.beam
index e80f8913a4..b664286f0f 100644
--- a/bootstrap/lib/compiler/ebin/beam_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 30777e45b8..50771f4e90 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index d15e27f507..c296bdd18d 100644
--- a/bootstrap/lib/compiler/ebin/beam_jump.beam
+++ b/bootstrap/lib/compiler/ebin/beam_jump.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index abd69e31fe..1aa160b998 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 9767c2b2cf..373c0afc0c 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index bbf9d34115..d03dfe646c 100644
--- a/bootstrap/lib/compiler/ebin/core_lib.beam
+++ b/bootstrap/lib/compiler/ebin/core_lib.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index 934d718214..e96e4bc654 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index 2d812b9922..a4529cdd39 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_inline.beam b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
index fa5ed774cd..b2762781e7 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_inline.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 5e29ac196e..a51af4dd43 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index ce71dd37bb..97a9a79260 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
index d263343393..8f18f5ff25 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index f142832816..cd96c87f99 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index 4a90e37aac..e9f463867e 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index 2a7e46faf5..4338bb4687 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
index 148a74fe49..dd2d62b8a0 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index a3081261a2..4fd0b25503 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index c5a2398824..1b92542df2 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
index e794a5e94c..39389454f9 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index f27b82d841..ebb9ed19d5 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/include/file.hrl b/bootstrap/lib/kernel/include/file.hrl
index bf97173122..69aec1ee36 100644
--- a/bootstrap/lib/kernel/include/file.hrl
+++ b/bootstrap/lib/kernel/include/file.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,32 +22,37 @@
%%--------------------------------------------------------------------------
-record(file_info,
- {size :: non_neg_integer(), % Size of file in bytes.
- type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
- access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time() | integer(), % The local time the file was last read:
- % {{Year, Mon, Day}, {Hour, Min, Sec}}.
- % atime, ctime, mtime may also be unix epochs()
- mtime :: file:date_time() | integer(), % The local time the file was last written.
- ctime :: file:date_time() | integer(), % The interpretation of this time field
- % is dependent on operating system.
- % On Unix it is the last time the file
- % or the inode was changed. On Windows,
- % it is the creation time.
- mode :: integer(), % File permissions. On Windows,
- % the owner permissions will be
- % duplicated for group and user.
- links :: non_neg_integer(), % Number of links to the file (1 if the
- % filesystem doesn't support links).
- major_device :: integer(), % Identifies the file system (Unix),
- % or the drive number (A: = 0, B: = 1)
- % (Windows).
- %% The following are Unix specific.
- %% They are set to zero on other operating systems.
- minor_device :: integer(), % Only valid for devices.
- inode :: integer(), % Inode number for file.
- uid :: integer(), % User id for owner.
- gid :: integer()}). % Group id for owner.
+ {size :: non_neg_integer(), % Size of file in bytes.
+ type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
+ access :: 'read' | 'write' | 'read_write' | 'none',
+ atime :: file:date_time() | non_neg_integer(),
+ % The local time the file was last read:
+ % {{Year, Mon, Day}, {Hour, Min, Sec}}.
+ % atime, ctime, mtime may also be unix epochs()
+ mtime :: file:date_time() | non_neg_integer(),
+ % The local time the file was last written.
+ ctime :: file:date_time() | non_neg_integer(),
+ % The interpretation of this time field
+ % is dependent on operating system.
+ % On Unix it is the last time the file
+ % or the inode was changed. On Windows,
+ % it is the creation time.
+ mode :: non_neg_integer(), % File permissions. On Windows,
+ % the owner permissions will be
+ % duplicated for group and user.
+ links :: non_neg_integer(),
+ % Number of links to the file (1 if the
+ % filesystem doesn't support links).
+ major_device :: non_neg_integer(),
+ % Identifies the file system (Unix),
+ % or the drive number (A: = 0, B: = 1)
+ % (Windows).
+ %% The following are Unix specific.
+ %% They are set to zero on other operating systems.
+ minor_device :: non_neg_integer(), % Only valid for devices.
+ inode :: non_neg_integer(), % Inode number for file.
+ uid :: non_neg_integer(), % User id for owner.
+ gid :: non_neg_integer()}). % Group id for owner.
-record(file_descriptor,
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index 19f589980f..48ed694380 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index f9b99f574c..06ace1f82d 100644
--- a/bootstrap/lib/stdlib/ebin/dets_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index a5957fc9ce..9bab801654 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam
index 3eac2b2000..bb586c5f6a 100644
--- a/bootstrap/lib/stdlib/ebin/edlin.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index a3a86afce9..168bd3e878 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 20b6d9cd44..b387a2c62c 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 0b274c9630..ee3064f9e1 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index 9c5c72af30..52759b0ea5 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index ef47d3a06c..56d710de2a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index 4cb833bb30..89ee92fddb 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index e255819b70..7d0554106e 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam
index be35e0124e..37b6753300 100644
--- a/bootstrap/lib/stdlib/ebin/gen_event.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_event.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
index 06782fbf91..1fcabac0d7 100644
--- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam
index 0ccd003b0b..f0fa4f03a9 100644
--- a/bootstrap/lib/stdlib/ebin/gen_server.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index 68b6d0da56..948af8d1be 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 9a9bfa4e2f..8ad59de20d 100644
--- a/bootstrap/lib/stdlib/ebin/pool.beam
+++ b/bootstrap/lib/stdlib/ebin/pool.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
index eb098b31ae..458684586b 100644
--- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/queue.beam b/bootstrap/lib/stdlib/ebin/queue.beam
index 688c411798..8907a03b57 100644
--- a/bootstrap/lib/stdlib/ebin/queue.beam
+++ b/bootstrap/lib/stdlib/ebin/queue.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index 5a7ddd5f56..d8d65c5521 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index e06badfec4..841874f1f5 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 9869d4862b..572cb2b6fa 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index 41386df3f0..e8492c52bc 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/erts/configure.in b/erts/configure.in
index 30bc1ef000..a0c5cab181 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -827,6 +827,12 @@ if test -z "$FOP"; then
AC_MSG_WARN([No 'fop' command found: going to generate placeholder PDF files])
fi
+AC_CHECK_PROGS(XMLLINT, xmllint)
+if test -z "$XMLLINT"; then
+ echo "xmllint" >> doc/CONF_INFO
+ AC_MSG_WARN([No 'xmllint' command found: can't run the xmllint target for the documentation])
+fi
+
dnl
dnl We can live with Solaris /usr/ucb/install
dnl
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 4455d0ac92..d036b4c7fb 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -290,13 +290,6 @@
<item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c>
where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
<c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item>
- <item>If E is <c><![CDATA[query [E_0 || W_1, ..., W_k] end]]></c>,
- where each <c><![CDATA[W_i]]></c> is a generator or a filter, then
- Rep(E) = <c><![CDATA[{'query',LINE,{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}}]]></c>.
- For Rep(W), see below.</item>
- <item>If E is <c><![CDATA[E_0.Field]]></c>, a Mnesia record access
- inside a query, then
- Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Rep(Field)}]]></c>.</item>
<item>If E is <c><![CDATA[( E_0 )]]></c>, then
Rep(E) = <c><![CDATA[Rep(E_0)]]></c>,
i.e., parenthesized expressions cannot be distinguished from their bodies.</item>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 99f2466d79..37c7f3466b 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -479,7 +479,7 @@
<tag><marker id="async_thread_pool_size"><c><![CDATA[+A size]]></c></marker></tag>
<item>
<p>Sets the number of threads in async thread pool, valid range
- is 0-1024. Default is 0.</p>
+ is 0-1024. If thread support is available, the default is 10.</p>
</item>
<tag><c><![CDATA[+B [c | d | i]]]></c></tag>
<item>
@@ -582,7 +582,7 @@
<seealso marker="erts_alloc">erts_alloc(3)</seealso> for
further information.</p>
</item>
- <tag><c><![CDATA[+n Behavior]]></c></tag>
+ <tag><marker id="+n"/><c><![CDATA[+n Behavior]]></c></tag>
<item>
<p>Control behavior of signals to ports.</p>
<p>As of OTP-R16 signals to ports are truly asynchronously
@@ -615,7 +615,7 @@
debugging.</item>
</taglist>
</item>
- <tag><marker id="max_processes"><c><![CDATA[+P Number]]></c></marker></tag>
+ <tag><marker id="+P"/><marker id="max_processes"><c><![CDATA[+P Number]]></c></marker></tag>
<item>
<p>Sets the maximum number of simultaneously existing processes for this
system. Valid range for <c>Number</c> is <c>[1024-134217727]</c></p>
@@ -627,7 +627,7 @@
<seealso marker="erlang#system_info_process_limit">erlang:system_info(process_limit)</seealso>.</p>
<p>The default value is <c>262144</c></p>
</item>
- <tag><marker id="max_ports"><c><![CDATA[+Q Number]]></c></marker></tag>
+ <tag><marker id="+Q"/><marker id="max_ports"><c><![CDATA[+Q Number]]></c></marker></tag>
<item>
<p>Sets the maximum number of simultaneously existing ports for this
system. Valid range for <c>Number</c> is <c>[1024-134217727]</c></p>
@@ -672,7 +672,7 @@
<item>
<p>Limits the amount of reader groups used by read/write locks
optimized for read operations in the Erlang runtime system. By
- default the reader groups limit equals 8.</p>
+ default the reader groups limit equals 64.</p>
<p>When the amount of schedulers is less than or equal to the reader
groups limit, each scheduler has its own reader group. When the
amount of schedulers is larger than the reader groups limit,
@@ -710,7 +710,24 @@
<taglist>
<tag><marker id="+sbt"><c>+sbt BindType</c></marker></tag>
<item>
- <p>Set scheduler bind type. Currently valid <c>BindType</c>s:
+ <p>Set scheduler bind type.</p>
+ <p>Schedulers can also be bound using the
+ <seealso marker="#+stbt">+stbt</seealso> flag. The only difference
+ between these two flags is how the following errors are handled:</p>
+ <list>
+ <item>Binding of schedulers is not supported on the specific
+ platform.</item>
+ <item>No available CPU topology. That is the runtime system
+ was not able to automatically detected the CPU topology, and
+ no <seealso marker="#+sct">user defined CPU topology</seealso>
+ was set.</item>
+ </list>
+ <p>If any of these errors occur when <c>+sbt</c> has been passed,
+ the runtime system will print an error message, and refuse to
+ start. If any of these errors occur when <c>+stbt</c> has been
+ passed, the runtime system will silently ignore the error, and
+ start up using unbound schedulers.</p>
+ <p>Currently valid <c>BindType</c>s:
</p>
<taglist>
<tag><c>u</c></tag>
@@ -960,6 +977,14 @@
<p>For more information, see
<seealso marker="erlang#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>.</p>
</item>
+ <tag><marker id="+stbt"><c>+stbt BindType</c></marker></tag>
+ <item>
+ <p>Try to set scheduler bind type. The same as the
+ <seealso marker="#+sbt">+sbt</seealso> flag with the exception of
+ how some errors are handled. For more information, see the
+ documentation of the <seealso marker="#+sbt">+sbt</seealso> flag.
+ </p>
+ </item>
<tag><marker id="+sws"><c>+sws default|legacy|proposal</c></marker></tag>
<item>
<p>Set scheduler wakeup strategy. Default is <c>legacy</c> (has been
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 13f42a74a7..1212c34586 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -317,9 +317,9 @@
minor version used by the driver is greater than the one used
by the runtime system.</p>
<p>The emulator will refuse to load a driver that does not use
- the extended driver interface since,
+ the extended driver interface,
to allow for 64-bit capable drivers,
- incompatible type changes for the callbacks
+ since incompatible type changes for the callbacks
<seealso marker="driver_entry#output">output</seealso>,
<seealso marker="driver_entry#control">control</seealso> and
<seealso marker="driver_entry#call">call</seealso>
@@ -1560,7 +1560,7 @@ typedef struct ErlIOVec {
<c>[ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]</c>.
Limits will be automatically adjusted to be sane. That is,
the system will adjust values so that the low limit used is
- lower or equal to the high limit used. By default the high
+ lower than or equal to the high limit used. By default the high
limit will be 8 kB and the low limit will be 4 kB.</p>
<p>By passing a pointer to an integer variable containing
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 1d67be2e52..ce59908036 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -5679,35 +5679,35 @@ ok
For more information see the
<seealso marker="erl#+spp">+spp</seealso> command line argument
of <seealso marker="erl">erl(1)</seealso>.</p></item>
- <tag><c>process_count</c></tag>
+ <tag><marker id="system_info_port_count"/><c>port_count</c></tag>
<item>
<p>Returns the number of ports currently existing at
the local node as an integer. The same value as
- <c>length(erlang:ports())</c> returns.</p>
+ <c>length(erlang:ports())</c> returns, but more efficient.</p>
</item>
<tag><marker id="system_info_port_limit"><c>port_limit</c></marker></tag>
<item>
<p>Returns the maximum number of simultaneously existing
ports at the local node as an integer. This limit
can be configured at startup by using the
- <seealso marker="erl#max_ports"><c>+Q</c></seealso>
+ <seealso marker="erl#+Q">+Q</seealso>
command line flag of
- <seealso marker="erl"><c>erl(1)</c></seealso>.</p>
+ <seealso marker="erl">erl(1)</seealso>.</p>
</item>
- <tag><c>process_count</c></tag>
+ <tag><marker id="system_info_process_count"/><c>process_count</c></tag>
<item>
<p>Returns the number of processes currently existing at
the local node as an integer. The same value as
- <c>length(processes())</c> returns.</p>
+ <c>length(processes())</c> returns, but more efficient.</p>
</item>
<tag><marker id="system_info_process_limit"><c>process_limit</c></marker></tag>
<item>
<p>Returns the maximum number of simultaneously existing
processes at the local node as an integer. This limit
can be configured at startup by using the
- <seealso marker="erl#max_processes"><c>+P</c></seealso>
+ <seealso marker="erl#+P">+P</seealso>
command line flag of
- <seealso marker="erl"><c>erl(1)</c></seealso>.</p>
+ <seealso marker="erl">erl(1)</seealso>.</p>
</item>
<tag><c>procs</c></tag>
<item>
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 71f232035d..4e456988a3 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -59,6 +59,8 @@ do { \
} while(0)
#define BUMP_REDS(p, gc) do { \
+ ASSERT(p); \
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
(p)->fcalls -= (gc); \
if ((p)->fcalls < 0) { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) \
diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c
index 3f90f34736..88456a85f3 100644
--- a/erts/emulator/beam/erl_cpu_topology.c
+++ b/erts/emulator/beam/erl_cpu_topology.c
@@ -34,7 +34,7 @@
#include "bif.h"
#include "erl_cpu_topology.h"
-#define ERTS_MAX_READER_GROUPS 8
+#define ERTS_MAX_READER_GROUPS 64
/*
* Cpu topology hierarchy.
@@ -620,30 +620,38 @@ write_schedulers_bind_change(erts_cpu_topology_t *cpudata, int size)
int
erts_init_scheduler_bind_type_string(char *how)
{
+ ErtsCpuBindOrder order;
+
if (sys_strcmp(how, "u") == 0)
- cpu_bind_order = ERTS_CPU_BIND_NONE;
- else if (erts_bind_to_cpu(cpuinfo, -1) == -ENOTSUP)
- return ERTS_INIT_SCHED_BIND_TYPE_NOT_SUPPORTED;
- else if (!system_cpudata && !user_cpudata)
- return ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY;
+ order = ERTS_CPU_BIND_NONE;
else if (sys_strcmp(how, "db") == 0)
- cpu_bind_order = ERTS_CPU_BIND_DEFAULT_BIND;
+ order = ERTS_CPU_BIND_DEFAULT_BIND;
else if (sys_strcmp(how, "s") == 0)
- cpu_bind_order = ERTS_CPU_BIND_SPREAD;
+ order = ERTS_CPU_BIND_SPREAD;
else if (sys_strcmp(how, "ps") == 0)
- cpu_bind_order = ERTS_CPU_BIND_PROCESSOR_SPREAD;
+ order = ERTS_CPU_BIND_PROCESSOR_SPREAD;
else if (sys_strcmp(how, "ts") == 0)
- cpu_bind_order = ERTS_CPU_BIND_THREAD_SPREAD;
+ order = ERTS_CPU_BIND_THREAD_SPREAD;
else if (sys_strcmp(how, "tnnps") == 0)
- cpu_bind_order = ERTS_CPU_BIND_THREAD_NO_NODE_PROCESSOR_SPREAD;
+ order = ERTS_CPU_BIND_THREAD_NO_NODE_PROCESSOR_SPREAD;
else if (sys_strcmp(how, "nnps") == 0)
- cpu_bind_order = ERTS_CPU_BIND_NO_NODE_PROCESSOR_SPREAD;
+ order = ERTS_CPU_BIND_NO_NODE_PROCESSOR_SPREAD;
else if (sys_strcmp(how, "nnts") == 0)
- cpu_bind_order = ERTS_CPU_BIND_NO_NODE_THREAD_SPREAD;
+ order = ERTS_CPU_BIND_NO_NODE_THREAD_SPREAD;
else if (sys_strcmp(how, "ns") == 0)
- cpu_bind_order = ERTS_CPU_BIND_NO_SPREAD;
+ order = ERTS_CPU_BIND_NO_SPREAD;
else
- return ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_BAD_TYPE;
+ return ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE;
+
+ if (order != ERTS_CPU_BIND_NONE) {
+ if (erts_bind_to_cpu(cpuinfo, -1) == -ENOTSUP)
+ return ERTS_INIT_SCHED_BIND_TYPE_NOT_SUPPORTED;
+ else if (!system_cpudata && !user_cpudata)
+ return ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY;
+ }
+
+ cpu_bind_order = order;
+
return ERTS_INIT_SCHED_BIND_TYPE_SUCCESS;
}
diff --git a/erts/emulator/beam/erl_cpu_topology.h b/erts/emulator/beam/erl_cpu_topology.h
index c5a9520b61..11915e1ea8 100644
--- a/erts/emulator/beam/erl_cpu_topology.h
+++ b/erts/emulator/beam/erl_cpu_topology.h
@@ -40,7 +40,7 @@ void erts_init_cpu_topology(void);
#define ERTS_INIT_SCHED_BIND_TYPE_SUCCESS 0
#define ERTS_INIT_SCHED_BIND_TYPE_NOT_SUPPORTED 1
#define ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY 2
-#define ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_BAD_TYPE 3
+#define ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE 3
int erts_init_scheduler_bind_type_string(char *how);
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 8cdf954dd2..b518683730 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -55,6 +55,8 @@
# include <sys/resource.h>
#endif
+#define ERTS_DEFAULT_NO_ASYNC_THREADS 10
+
/*
* The variables below (prefixed with etp_) are for erts/etc/unix/etp-commands
* only. Do not remove even though they aren't used elsewhere in the emulator!
@@ -521,7 +523,7 @@ void erts_usage(void)
erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n");
erts_fprintf(stderr, "-rg amount set reader groups limit\n");
erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n");
- erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
+ erts_fprintf(stderr, "-stbt type u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
erts_fprintf(stderr, "-sbwt val set scheduler busy wait threshold, valid values are:\n");
erts_fprintf(stderr, " none|very_short|short|medium|long|very_long.\n");
erts_fprintf(stderr, "-scl bool enable/disable compaction of scheduler load,\n");
@@ -529,7 +531,7 @@ void erts_usage(void)
erts_fprintf(stderr, "-sct cput set cpu topology,\n");
erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
erts_fprintf(stderr, "-sws val set scheduler wakeup strategy, valid values are:\n");
- erts_fprintf(stderr, " default|legacy|proposal.\n");
+ erts_fprintf(stderr, " default|legacy.\n");
erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n");
erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
@@ -631,7 +633,7 @@ early_init(int *argc, char **argv) /*
erts_disable_tolerant_timeofday = 0;
display_items = 200;
erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE;
- erts_async_max_threads = 0;
+ erts_async_max_threads = ERTS_DEFAULT_NO_ASYNC_THREADS;
erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE;
H_MIN_SIZE = H_DEFAULT_SIZE;
BIN_VH_MIN_SIZE = VH_DEFAULT_SIZE;
@@ -700,7 +702,7 @@ early_init(int *argc, char **argv) /*
if (erts_sys_getenv__("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0)
erts_async_max_threads = atoi(envbuf);
else
- erts_async_max_threads = 0;
+ erts_async_max_threads = ERTS_DEFAULT_NO_ASYNC_THREADS;
if (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)
erts_async_max_threads = ERTS_MAX_NO_OF_ASYNC_THREADS;
@@ -1238,7 +1240,7 @@ erl_start(int argc, char **argv)
case ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY:
estr = "no cpu topology available";
break;
- case ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_BAD_TYPE:
+ case ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE:
estr = "invalid type";
break;
default:
@@ -1333,6 +1335,16 @@ erl_start(int argc, char **argv)
}
else if (sys_strcmp("nsp", sub_param) == 0)
erts_use_sender_punish = 0;
+ else if (has_prefix("tbt", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ res = erts_init_scheduler_bind_type_string(arg);
+ if (res == ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE) {
+ erts_fprintf(stderr,
+ "setting scheduler bind type '%s' failed: invalid type\n",
+ arg);
+ erts_usage();
+ }
+ }
else if (sys_strcmp("wt", sub_param) == 0) {
arg = get_arg(sub_param+2, argv[i+1], &i);
if (erts_sched_set_wakeup_other_thresold(arg) != 0) {
@@ -1520,6 +1532,14 @@ erl_start(int argc, char **argv)
i++;
}
+/* Output format on windows for sprintf defaults to three exponents.
+ * We use two-exponent to mimic normal sprintf behaviour.
+ */
+
+#if defined(__WIN32__) && defined(_TWO_DIGIT_EXPONENT)
+ _set_output_format(_TWO_DIGIT_EXPONENT);
+#endif
+
/* Restart will not reinstall the break handler */
#ifdef __WIN32__
if (ignore_break)
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index fb07f3d5bc..65b4cd0bfe 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -273,29 +273,28 @@ extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
(ERTS_PORT_SFLGS_INVALID_LOOKUP \
| ERTS_PORT_SFLG_DISTRIBUTION)
-
/*
* Costs in reductions for some port operations.
*/
-#define ERTS_PORT_REDS_EXECUTE 10
-#define ERTS_PORT_REDS_FREE 100
-#define ERTS_PORT_REDS_TIMEOUT 400
-#define ERTS_PORT_REDS_INPUT 400
-#define ERTS_PORT_REDS_OUTPUT 400
-#define ERTS_PORT_REDS_EVENT 400
-#define ERTS_PORT_REDS_CMD_OUTPUTV 400
-#define ERTS_PORT_REDS_CMD_OUTPUT 400
-#define ERTS_PORT_REDS_EXIT 300
-#define ERTS_PORT_REDS_CONNECT 40
-#define ERTS_PORT_REDS_UNLINK 40
-#define ERTS_PORT_REDS_LINK 40
-#define ERTS_PORT_REDS_BADSIG 40
-#define ERTS_PORT_REDS_CONTROL 400
-#define ERTS_PORT_REDS_CALL 400
-#define ERTS_PORT_REDS_INFO 100
-#define ERTS_PORT_REDS_SET_DATA 40
-#define ERTS_PORT_REDS_GET_DATA 40
-#define ERTS_PORT_REDS_TERMINATE 200
+#define ERTS_PORT_REDS_EXECUTE (CONTEXT_REDS/4)
+#define ERTS_PORT_REDS_FREE (CONTEXT_REDS/400)
+#define ERTS_PORT_REDS_TIMEOUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_INPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_OUTPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_EVENT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CMD_OUTPUTV (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CMD_OUTPUT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_EXIT (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CONNECT (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_UNLINK (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_LINK (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_BADSIG (CONTEXT_REDS/200)
+#define ERTS_PORT_REDS_CONTROL (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_CALL (CONTEXT_REDS/50)
+#define ERTS_PORT_REDS_INFO (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_SET_DATA (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_GET_DATA (CONTEXT_REDS/100)
+#define ERTS_PORT_REDS_TERMINATE (CONTEXT_REDS/50)
void print_port_info(Port *, int, void *);
void erts_port_free(Port *);
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 8ceadcdb8c..09c8e760f4 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -35,6 +35,11 @@
#include "dtrace-wrapper.h"
#include <stdarg.h>
+/*
+ * ERTS_PORT_CALLBACK_VREDS: Limit the amount of callback calls we do...
+ */
+#define ERTS_PORT_CALLBACK_VREDS (CONTEXT_REDS/5)
+
#if defined(DEBUG) && 0
#define ERTS_HARD_DEBUG_TASK_QUEUES
#else
@@ -1544,6 +1549,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
ErtsPortTask *execq;
int processing_busy_q;
int res = 0;
+ int vreds = 0;
int reds = ERTS_PORT_REDS_EXECUTE;
erts_aint_t io_tasks_executed = 0;
int fpe_was_unmasked;
@@ -1688,6 +1694,9 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
break;
}
+ vreds += ERTS_PORT_CALLBACK_VREDS;
+ reds += ERTS_PORT_CALLBACK_VREDS;
+
if (reds >= CONTEXT_REDS)
break;
}
@@ -1757,6 +1766,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
res = (erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
!= (erts_aint_t) 0);
+ reds -= vreds;
runq->scheduler->reductions += reds;
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index aaca4b5f59..6e9bf7ca12 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -4080,11 +4080,11 @@ typedef enum {
} ErtsSchedWakeupOtherThreshold;
typedef enum {
- ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL,
+ ERTS_SCHED_WAKEUP_OTHER_TYPE_DEFAULT,
ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY
} ErtsSchedWakeupOtherType;
-/* First proposal */
+/* Default */
#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH (200*CONTEXT_REDS)
#define ERTS_WAKEUP_OTHER_LIMIT_HIGH (50*CONTEXT_REDS)
@@ -4101,7 +4101,7 @@ typedef enum {
#define ERTS_WAKEUP_OTHER_DEC_SHIFT 2
#define ERTS_WAKEUP_OTHER_FIXED_INC (CONTEXT_REDS/10)
-/* To be legacy */
+/* Legacy */
#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH_LEGACY (200*CONTEXT_REDS)
#define ERTS_WAKEUP_OTHER_LIMIT_HIGH_LEGACY (50*CONTEXT_REDS)
@@ -4239,7 +4239,7 @@ static void
set_wakeup_other_data(void)
{
switch (wakeup_other.type) {
- case ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL:
+ case ERTS_SCHED_WAKEUP_OTHER_TYPE_DEFAULT:
wakeup_other.check = wakeup_other_check;
wakeup_other_set_limit();
break;
@@ -4258,7 +4258,7 @@ erts_early_init_scheduling(int no_schedulers)
aux_work_timeout_early_init(no_schedulers);
#ifdef ERTS_SMP
wakeup_other.threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM;
- wakeup_other.type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
+ wakeup_other.type = ERTS_SCHED_WAKEUP_OTHER_TYPE_DEFAULT;
#endif
sched_busy_wait.sys_schedule = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM;
sched_busy_wait.tse = (ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM
@@ -4294,10 +4294,8 @@ int
erts_sched_set_wakeup_other_type(char *str)
{
ErtsSchedWakeupOtherType type;
- if (sys_strcmp(str, "proposal") == 0)
- type = ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL;
- else if (sys_strcmp(str, "default") == 0)
- type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
+ if (sys_strcmp(str, "default") == 0)
+ type = ERTS_SCHED_WAKEUP_OTHER_TYPE_DEFAULT;
else if (sys_strcmp(str, "legacy") == 0)
type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
else
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index e466f0e299..04dc9bb236 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1573,6 +1573,8 @@ bad_port_signal(Process *c_p,
try_call_state.state,
flags & ERTS_PORT_SIG_FLG_BAD_OUTPUT);
finalize_imm_drv_call(&try_call_state);
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_BADSIG);
return ERTS_PORT_OP_BADARG;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -1950,10 +1952,11 @@ erts_port_output(Process *c_p,
driver_free_binary(cbin);
if (evp != &ev)
erts_free(ERTS_ALC_T_TMP, evp);
- if (try_call_res == ERTS_TRY_IMM_DRV_CALL_OK)
- return ERTS_PORT_OP_DONE;
- else
+ if (try_call_res != ERTS_TRY_IMM_DRV_CALL_OK)
return ERTS_PORT_OP_DROPPED;
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CMD_OUTPUTV);
+ return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
@@ -2096,10 +2099,11 @@ erts_port_output(Process *c_p,
/* Fall through... */
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
erts_free(ERTS_ALC_T_TMP, buf);
- if (try_call_res == ERTS_TRY_IMM_DRV_CALL_OK)
- return ERTS_PORT_OP_DONE;
- else
+ if (try_call_res != ERTS_TRY_IMM_DRV_CALL_OK)
return ERTS_PORT_OP_DROPPED;
+ if (c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CMD_OUTPUT);
+ return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
@@ -2267,6 +2271,8 @@ erts_port_exit(Process *c_p,
reason,
flags & ERTS_PORT_SIG_FLG_BROKEN_LINK);
finalize_imm_drv_call(&try_call_state);
+ if (res == ERTS_PORT_OP_DONE && c_p)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_EXIT);
return res;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -2434,6 +2440,8 @@ erts_port_connect(Process *c_p,
try_call_state.state,
connect_id);
finalize_imm_drv_call(&try_call_state);
+ if (res == ERTS_PORT_OP_DONE)
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CONNECT);
return res;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -2492,6 +2500,7 @@ erts_port_unlink(Process *c_p, Port *prt, Eterm from, Eterm *refp)
case ERTS_TRY_IMM_DRV_CALL_OK:
port_unlink(prt, from);
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_UNLINK);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -2579,6 +2588,7 @@ erts_port_link(Process *c_p, Port *prt, Eterm to, Eterm *refp)
case ERTS_TRY_IMM_DRV_CALL_OK:
port_link(prt, try_call_state.state, to);
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_LINK);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_BADARG;
@@ -3944,6 +3954,7 @@ erts_port_control(Process* c_p,
&hp,
NULL,
&c_p->off_heap);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CONTROL);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4244,6 +4255,7 @@ erts_port_call(Process* c_p,
if (resp_buf != &resp_buf[0]
&& !(ret_flags & DRIVER_CALL_KEEP_BUFFER))
driver_free(resp_buf);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_CALL);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4423,6 +4435,7 @@ erts_port_info(Process* c_p,
*retvalp = copy_struct(value, used_h_size, &hp, &MSO(c_p));
free_message_buffer(bp);
}
+ BUMP_REDS(c_p, ERTS_PORT_REDS_INFO);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
@@ -4509,6 +4522,7 @@ erts_port_set_data(Process* c_p,
prt->bp = bp;
prt->data = set_data;
finalize_imm_drv_call(&try_call_state);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_SET_DATA);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
return ERTS_PORT_OP_DROPPED;
@@ -4641,6 +4655,7 @@ erts_port_get_data(Process* c_p,
free_message_buffer(bp);
}
*retvalp = TUPLE2(hp, am_ok, data);
+ BUMP_REDS(c_p, ERTS_PORT_REDS_GET_DATA);
return ERTS_PORT_OP_DONE;
}
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 25b02db2c9..186af03eff 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -57,7 +57,7 @@
#define FILE_FADVISE 31
#define FILE_SENDFILE 32
#define FILE_FALLOCATE 33
-
+#define FILE_CLOSE_ON_PORT_EXIT 34
/* Return codes */
#define FILE_RESP_OK 0
@@ -178,6 +178,7 @@ dt_private *get_dt_private(int);
#define MUTEX_LOCK(m) do { IF_THRDS { TRACE_DRIVER; driver_pdl_lock(m); } } while (0)
#define MUTEX_UNLOCK(m) do { IF_THRDS { TRACE_DRIVER; driver_pdl_unlock(m); } } while (0)
#else
+#define IF_THRDS if (0)
#define MUTEX_INIT(m, p)
#define MUTEX_LOCK(m)
#define MUTEX_UNLOCK(m)
@@ -429,6 +430,7 @@ struct t_data
int level;
void (*invoke)(void *);
void (*free)(void *);
+ void *data_to_free; /* used by FILE_CLOSE_ON_PORT_EXIT only */
int again;
int reply;
#ifdef USE_VM_PROBES
@@ -808,34 +810,25 @@ static void free_data(void *data)
{
struct t_data *d = (struct t_data *) data;
- if (d->command == FILE_OPEN && d->is_fd_unused && d->fd != FILE_FD_INVALID) {
- do_close(d->flags, d->fd);
+ switch (d->command) {
+ case FILE_OPEN:
+ if (d->is_fd_unused && d->fd != FILE_FD_INVALID) {
+ /* This is OK to do in scheduler thread because there can be no async op
+ ongoing for this fd here, as we exited during async open.
+ Ideally, this close should happen in an async thread too, but that would
+ require a substantial rewrite, as we are here because of a dead port and
+ cannot schedule async jobs for that port any more... */
+ do_close(d->flags, d->fd);
+ }
+ break;
+ case FILE_CLOSE_ON_PORT_EXIT:
+ EF_FREE(d->data_to_free);
+ break;
}
EF_FREE(data);
}
-/*********************************************************************
- * Driver entry point -> stop
- */
-static void
-file_stop(ErlDrvData e)
-{
- file_descriptor* desc = (file_descriptor*)e;
-
- TRACE_C('p');
-
- if (desc->fd != FILE_FD_INVALID) {
- do_close(desc->flags, desc->fd);
- desc->fd = FILE_FD_INVALID;
- desc->flags = 0;
- }
- if (desc->read_binp) {
- driver_free_binary(desc->read_binp);
- }
- EF_FREE(desc);
-}
-
/*
* Sends back an error reply to Erlang.
@@ -2242,6 +2235,47 @@ static int lseek_flush_read(file_descriptor *desc, int *errp
}
+/*********************************************************************
+ * Driver entry point -> stop
+ * The close has to be scheduled on async thread, so that currently active
+ * async operation does not suddenly have the ground disappearing under their feet...
+ */
+static void
+file_stop(ErlDrvData e)
+{
+ file_descriptor* desc = (file_descriptor*)e;
+
+ TRACE_C('p');
+
+ IF_THRDS {
+ flush_read(desc);
+ if (desc->fd != FILE_FD_INVALID) {
+ struct t_data *d = EF_SAFE_ALLOC(sizeof(struct t_data));
+ d->command = FILE_CLOSE_ON_PORT_EXIT;
+ d->reply = !0;
+ d->fd = desc->fd;
+ d->flags = desc->flags;
+ d->invoke = invoke_close;
+ d->free = free_data;
+ d->level = 2;
+ d->data_to_free = (void *) desc;
+ cq_enq(desc, d);
+ desc->fd = FILE_FD_INVALID;
+ desc->flags = 0;
+ cq_execute(desc);
+ }
+ } else {
+ if (desc->fd != FILE_FD_INVALID) {
+ do_close(desc->flags, desc->fd);
+ desc->fd = FILE_FD_INVALID;
+ desc->flags = 0;
+ }
+ if (desc->read_binp) {
+ driver_free_binary(desc->read_binp);
+ }
+ EF_FREE(desc);
+ }
+}
/*********************************************************************
* Driver entry point -> ready_async
@@ -2465,7 +2499,6 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
}
free_readdir(data);
break;
- /* See file_stop */
case FILE_CLOSE:
if (d->reply) {
TRACE_C('K');
@@ -2525,6 +2558,15 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
}
break;
#endif
+ case FILE_CLOSE_ON_PORT_EXIT:
+ /* See file_stop. However this is never invoked after the port is killed. */
+ free_data(data);
+ EF_FREE(desc);
+ desc = NULL;
+ /* This is it for this port, so just send dtrace and return, avoid doing anything to the freed data */
+ DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag,
+ command, result_ok, posix_errno);
+ return;
default:
abort();
}
@@ -2535,6 +2577,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
driver_set_timer(desc->port, desc->write_delay);
}
cq_execute(desc);
+
}
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 236b8710fb..f0c22e9ebe 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -933,12 +933,20 @@ typedef struct {
int bufsz; /* minimum buffer constraint */
unsigned int hsz; /* the list header size, -1 is large !!! */
/* statistics */
- unsigned long recv_oct[2]; /* number of received octets >= 64 bits */
+#ifdef ARCH_64
+ Uint64 recv_oct; /* number of received octets, 64 bits */
+#else
+ Uint32 recv_oct[2]; /* number of received octets, 64 bits */
+#endif
unsigned long recv_cnt; /* number of packets received */
unsigned long recv_max; /* maximum packet size received */
double recv_avg; /* average packet size received */
double recv_dvi; /* avarage deviation from avg_size */
- unsigned long send_oct[2]; /* number of octets sent >= 64 bits */
+#ifdef ARCH_64
+ Uint64 send_oct; /* number of octets sent, 64 bits */
+#else
+ Uint32 send_oct[2]; /* number of octets sent, 64 bits */
+#endif
unsigned long send_cnt; /* number of packets sent */
unsigned long send_max; /* maximum packet send */
double send_avg; /* average packet size sent */
@@ -7377,13 +7385,21 @@ static ErlDrvSSizeT inet_fill_stat(inet_descriptor* desc,
val = (unsigned long) driver_sizeq(desc->port);
break;
case INET_STAT_RECV_OCT:
+#ifdef ARCH_64
+ put_int64(desc->recv_oct, dst); /* write it all */
+#else
put_int32(desc->recv_oct[1], dst); /* write high 32bit */
put_int32(desc->recv_oct[0], dst+4); /* write low 32bit */
+#endif
dst += 8;
continue;
case INET_STAT_SEND_OCT:
+#ifdef ARCH_64
+ put_int64(desc->send_oct, dst); /* write it all */
+#else
put_int32(desc->send_oct[1], dst); /* write high 32bit */
put_int32(desc->send_oct[0], dst+4); /* write low 32bit */
+#endif
dst += 8;
continue;
default: return -1; /* invalid argument */
@@ -7491,12 +7507,20 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
desc->peer_ptr = NULL;
desc->name_ptr = NULL;
+#ifdef ARCH_64
+ desc->recv_oct = 0;
+#else
desc->recv_oct[0] = desc->recv_oct[1] = 0;
+#endif
desc->recv_cnt = 0;
desc->recv_max = 0;
desc->recv_avg = 0.0;
desc->recv_dvi = 0.0;
+#ifdef ARCH_64
+ desc->send_oct = 0;
+#else
desc->send_oct[0] = desc->send_oct[1] = 0;
+#endif
desc->send_cnt = 0;
desc->send_max = 0;
desc->send_avg = 0.0;
@@ -7885,14 +7909,19 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
static void inet_output_count(inet_descriptor* desc, ErlDrvSizeT len)
{
unsigned long n = desc->send_cnt + 1;
- unsigned long t = desc->send_oct[0] + len;
+#ifndef ARCH_64
+ Uint32 t = desc->send_oct[0] + len;
int c = (t < desc->send_oct[0]);
+#endif
double avg = desc->send_avg;
- /* at least 64 bit octet count */
+#ifdef ARCH_64
+ desc->send_oct += len;
+#else
+ /* 64 bit octet count in 32 bit words */
desc->send_oct[0] = t;
desc->send_oct[1] += c;
-
+#endif
if (n == 0) /* WRAP, use old avg as input to a new sequence */
n = 1;
desc->send_avg += (len - avg) / n;
@@ -7905,14 +7934,20 @@ static void inet_output_count(inet_descriptor* desc, ErlDrvSizeT len)
static void inet_input_count(inet_descriptor* desc, ErlDrvSizeT len)
{
unsigned long n = desc->recv_cnt + 1;
- unsigned long t = desc->recv_oct[0] + len;
+#ifndef ARCH_64
+ Uint32 t = (desc->recv_oct[0] + len);
int c = (t < desc->recv_oct[0]);
+#endif
double avg = desc->recv_avg;
double dvi;
- /* at least 64 bit octet count */
+#ifdef ARCH_64
+ desc->recv_oct += len;
+#else
+ /* 64 bit octet count in 32 bit words */
desc->recv_oct[0] = t;
desc->recv_oct[1] += c;
+#endif
if (n == 0) /* WRAP */
n = 1;
@@ -9723,6 +9758,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
DEBUGF(("tcp_inet_output(%ld): s=%d, About to send %d items\r\n",
(long)desc->inet.port, desc->inet.s, vsize));
if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s, iov, vsize, &n, 0))) {
+ write_error:
if ((sock_errno() != ERRNO_BLOCK) && (sock_errno() != EINTR)) {
DEBUGF(("tcp_inet_output(%ld): sock_sendv(%d) errno = %d\r\n",
(long)desc->inet.port, vsize, sock_errno()));
@@ -9733,6 +9769,22 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
desc->inet.send_would_block = 1;
#endif
goto done;
+ } else if (n == 0) { /* Workaround for redhat/CentOS 6.3 returning
+ 0 when sending packets with
+ sizes > (max 32 bit signed int) */
+ size_t howmuch = 0x7FFFFFFF; /* max signed 32 bit */
+ int x;
+ for(x = 0; x < vsize && iov[x].iov_len == 0; ++x)
+ ;
+ if (x < vsize) {
+ if (howmuch > iov[x].iov_len) {
+ howmuch = iov[x].iov_len;
+ }
+ n = sock_send(desc->inet.s, iov[x].iov_base,howmuch,0);
+ if (IS_SOCKET_ERROR(n)) {
+ goto write_error;
+ }
+ }
}
if (driver_deq(ix, n) <= desc->low) {
if (IS_BUSY(INETP(desc))) {
diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c
index f5011d11a5..f2b0c8a843 100644
--- a/erts/emulator/drivers/win32/win_efile.c
+++ b/erts/emulator/drivers/win32/win_efile.c
@@ -41,6 +41,8 @@
#define IS_DOT_OR_DOTDOT(s) \
((s)[0] == L'.' && ((s)[1] == L'\0' || ((s)[1] == L'.' && (s)[2] == L'\0')))
+#define FILE_SHARE_FLAGS (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
+
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD) 0xFFFFFFFF)
#endif
@@ -724,7 +726,7 @@ efile_openfile(Efile_error* errInfo, /* Where to return error codes. */
crFlags = CREATE_NEW;
}
fd = CreateFileW(wname, access,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_SHARE_FLAGS,
NULL, crFlags, FILE_ATTRIBUTE_NORMAL, NULL);
/*
@@ -909,7 +911,7 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
{
HANDLE handle; /* Handle returned by CreateFile() */
BY_HANDLE_FILE_INFORMATION fileInfo; /* from CreateFile() */
- if (handle = CreateFileW(name, GENERIC_READ, 0,NULL,
+ if (handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_FLAGS, NULL,
OPEN_EXISTING, 0, NULL)) {
GetFileInformationByHandle(handle, &fileInfo);
pInfo->links = fileInfo.nNumberOfLinks;
@@ -1021,7 +1023,7 @@ efile_write_info(Efile_error* errInfo,
}
fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SHARE_FLAGS,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd != INVALID_HANDLE_VALUE) {
BOOL result = SetFileTime(fd, &CreationFileTime, &AccessFileTime, &ModifyFileTime);
@@ -1384,7 +1386,7 @@ efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
DWORD fileAttributes = GetFileAttributesW(wname);
if ((fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
BOOLEAN success = 0;
- HANDLE h = CreateFileW(wname, GENERIC_READ, 0,NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ HANDLE h = CreateFileW(wname, GENERIC_READ, FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
int len;
if(h != INVALID_HANDLE_VALUE) {
success = pGetFinalPathNameByHandle(h, wbuffer, size / sizeof(WCHAR),0);
diff --git a/erts/emulator/hipe/hipe_x86_gc.h b/erts/emulator/hipe/hipe_x86_gc.h
index aa4abb6f59..4bea9276c0 100644
--- a/erts/emulator/hipe/hipe_x86_gc.h
+++ b/erts/emulator/hipe/hipe_x86_gc.h
@@ -71,7 +71,7 @@ nstack_walk_init_sdesc(const Process *p, struct nstack_walk_state *state)
state->sdesc0[0].livebits[0] = 0;
# ifdef DEBUG
state->sdesc0[0].dbg_M = 0;
- state->sdesc0[0].dbg_F = am_init;
+ state->sdesc0[0].dbg_F = am_undefined;
state->sdesc0[0].dbg_A = 0;
# endif
/* XXX: this appears to prevent a gcc-4.1.1 bug on x86 */
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
index 66971654a2..5c4b11454f 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
@@ -42,6 +42,7 @@
typedef struct {
TestCaseState_t visible;
ErlDrvPort port;
+ ErlDrvTermData port_id;
int result;
jmp_buf done_jmp_buf;
char *comment;
@@ -97,6 +98,7 @@ testcase_drv_start(ErlDrvPort port, char *command)
itcs->visible.testcase_name = testcase_name();
itcs->visible.extra = NULL;
itcs->port = port;
+ itcs->port_id = driver_mk_port(port);
itcs->result = TESTCASE_FAILED;
itcs->comment = "";
@@ -142,7 +144,7 @@ testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
msg[1] = (ErlDrvTermData) result_atom;
msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
+ msg[3] = itcs->port_id;
msg[4] = ERL_DRV_ATOM;
msg[5] = driver_mk_atom(itcs->visible.testcase_name);
@@ -154,7 +156,7 @@ testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
msg[9] = ERL_DRV_TUPLE;
msg[10] = (ErlDrvTermData) 4;
- driver_output_term(itcs->port, msg, 11);
+ erl_drv_output_term(itcs->port_id, msg, 11);
}
int
@@ -184,7 +186,7 @@ testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
msg[1] = (ErlDrvTermData) driver_mk_atom("print");
msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
+ msg[3] = itcs->port_id;
msg[4] = ERL_DRV_ATOM;
msg[5] = driver_mk_atom(itcs->visible.testcase_name);
@@ -196,7 +198,7 @@ testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
msg[9] = ERL_DRV_TUPLE;
msg[10] = (ErlDrvTermData) 4;
- driver_output_term(itcs->port, msg, 11);
+ erl_drv_output_term(itcs->port_id, msg, 11);
}
diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl
index 32e907ca69..a92afef003 100644
--- a/erts/emulator/test/busy_port_SUITE.erl
+++ b/erts/emulator/test/busy_port_SUITE.erl
@@ -26,6 +26,8 @@
no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1,
hard_busy_driver/1, soft_busy_driver/1]).
+-compile(export_all).
+
-include_lib("test_server/include/test_server.hrl").
%% Internal exports.
@@ -36,7 +38,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[io_to_busy, message_order, send_3, system_monitor,
no_trap_exit, no_trap_exit_unlinked, trap_exit,
- multiple_writers, hard_busy_driver, soft_busy_driver].
+ multiple_writers, hard_busy_driver, soft_busy_driver,
+ scheduling_delay_busy,scheduling_delay_busy_nosuspend,
+ scheduling_busy_link].
groups() ->
[].
@@ -528,6 +532,304 @@ hs_busy_pcmd(Prt, Opts, StartFun, EndFun) ->
EndFun(P, Res, Time)
end.
+scheduling_delay_busy(Config) ->
+
+ Scenario =
+ [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {3,{spawn,[{var,2},{var,1}]}},
+ {0,{ack,[{var,1},{busy,1,250}]}},
+ {0,{cast,[{var,3},{command,2}]}},
+ [{0,{cast,[{var,3},{command,I}]}}
+ || I <- lists:seq(3,50)],
+ {0,{cast,[{var,3},take_control]}},
+ {0,{cast,[{var,1},{new_owner,{var,3}}]}},
+ {0,{cast,[{var,3},close]}},
+ {0,{timer,sleep,[300]}},
+ {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
+ [{0,{cast,[{var,1},{command,I}]}}
+ || I <- lists:seq(101,127)]
+ ,{10,{call,[{var,3},get_data]}}
+ ],
+
+ Validation = [{seq,10,lists:seq(1,50)}],
+
+ port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+
+scheduling_delay_busy_nosuspend(Config) ->
+
+ Scenario =
+ [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {0,{cast,[{var,1},{command,1,100}]}},
+ {0,{cast,[{var,1},{busy,2}]}},
+ {10,{call,[{var,1},{command,3,[nosuspend]}]}},
+ {0,{timer,sleep,[200]}},
+ {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
+ {0,{cast,[{var,1},close]}},
+ {20,{call,[{var,1},get_data]}}
+ ],
+
+ Validation = [{eq,10,nosuspend},{seq,20,[1,2]}],
+
+ port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+
+scheduling_busy_link(Config) ->
+
+ Scenario =
+ [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {3,{spawn,[{var,2},{var,1}]}},
+ {0,{cast,[{var,1},unlink]}},
+ {0,{cast,[{var,1},{busy,1}]}},
+ {0,{cast,[{var,1},{command,2}]}},
+ {0,{cast,[{var,1},link]}},
+ {0,{timer,sleep,[1000]}},
+ {0,{ack,[{var,3},take_control]}},
+ {0,{cast,[{var,1},{new_owner,{var,3}}]}},
+ {0,{cast,[{var,3},close]}},
+ {10,{call,[{var,3},get_data]}},
+ {20,{call,[{var,1},get_exit]}}
+ ],
+
+ Validation = [{seq,10,[1]},
+ {seq,20,[{'EXIT',noproc}]}],
+
+ port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+
+process_init(DrvName,Owner) ->
+ process_flag(trap_exit,true),
+ process_loop(DrvName,Owner, {[],[]}).
+
+process_loop(DrvName,undefined,Data) when is_list(DrvName) ->
+ process_loop(DrvName,[binary],Data);
+process_loop(DrvName,PortOpts,Data) when is_list(DrvName) ->
+ receive
+ {call,open_port,P} ->
+ Port = open_port({spawn, DrvName}, PortOpts),
+ send(P,Port),
+ process_loop(Port,self(),Data)
+ end;
+process_loop(Port,undefined,Data) ->
+ receive
+ {cast,{new_owner,Pid}} ->
+ pal("NewOwner: ~p",[Pid]),
+ process_loop(Port,Pid,Data)
+ end;
+process_loop(Port,Owner,{Data,Exit} = DE) ->
+ receive
+ {Port,connected} ->
+ pal("Connected",[]),
+ process_loop(Port,undefined,DE);
+ {Port,{data,NewData}} ->
+ pal("Got: ~p",[NewData]),
+ receive
+ {Port,closed} ->
+ process_loop(Port,Owner,{Data ++ [NewData],Exit})
+ after 2000 ->
+ exit(did_not_get_port_close)
+ end;
+ {'EXIT',Port,Reason} = Exit ->
+ pal("Exit: ~p",[Exit]),
+ process_loop(Port,Owner,{Data, Exit ++ [[{'EXIT',Reason}]]});
+ {'EXIT',_Port,_Reason} = Exit ->
+ pal("Exit: ~p",[Exit]);
+ {call,Msg,P} ->
+ case handle_msg(Msg,Port,Owner,DE) of
+ {Reply,NewOwner,NewData} ->
+ send(P,Reply),
+ process_loop(Port,NewOwner,NewData);
+ Reply ->
+ send(P,Reply),
+ process_loop(Port,Owner,DE)
+ end;
+ {ack,Msg,P} ->
+ send(P,ok),
+ case handle_msg(Msg,Port,Owner,DE) of
+ {_Reply,NewOwner,NewData} ->
+ process_loop(Port,NewOwner,NewData);
+ _Reply ->
+ process_loop(Port,Owner,DE)
+ end;
+ {cast,Msg} when is_atom(Msg) orelse element(1,Msg) /= new_owner ->
+ case handle_msg(Msg,Port,Owner,DE) of
+ {_Reply,NewOwner,NewData} ->
+ process_loop(Port,NewOwner,NewData);
+ _ ->
+ process_loop(Port,Owner,DE)
+ end
+ end.
+
+handle_msg({busy,Value,Delay},Port,Owner,_Data) ->
+ pal("Long busy: ~p",[Value]),
+ send(Port,{Owner,{command,<<$L,Value:32,(round(Delay/100))>>}});
+handle_msg({busy,Value},Port,Owner,_Data) ->
+ pal("Busy: ~p",[Value]),
+ send(Port,{Owner,{command,<<$B,Value:32>>}});
+handle_msg({command,Value},Port,Owner,_Data) ->
+ pal("Short: ~p",[Value]),
+ send(Port,{Owner,{command,<<$C,Value:32>>}});
+handle_msg({command,Value,Delay},Port,Owner,_Data) when is_integer(Delay) ->
+ pal("Long: ~p",[Value]),
+ send(Port,{Owner,{command,<<$D,Value:32,(round(Delay/100))>>}});
+handle_msg({command,Value,Opts},Port,Owner,_Data) ->
+ pal("Short Opt: ~p",[Value]),
+ send(Port,{Owner,{command,<<$C,Value:32>>}},Opts);
+handle_msg({command,Value,Opts,Delay},Port,Owner,_Data) ->
+ pal("Long Opt: ~p",[Value]),
+ send(Port,{Owner,{command,<<$D,Value:32,(round(Delay/100))>>}},Opts);
+handle_msg(take_control,Port,Owner,Data) ->
+ pal("Connect: ~p",[self()]),
+ send(Port,{Owner, {connect, self()}}),
+ {undefined,self(),Data};
+handle_msg(unlink,Port,_Owner,_Data) ->
+ pal("Unlink:",[]),
+ erlang:unlink(Port);
+handle_msg(link,Port,_Owner,_Data) ->
+ pal("Link:",[]),
+ erlang:link(Port);
+handle_msg(close,Port,Owner,_Data) ->
+ pal("Close",[]),
+ send(Port,{Owner,close});
+handle_msg(get_data,Port,_Owner,{[],_Exit}) ->
+ %% Wait for data if it has not arrived yet
+ receive
+ {Port,{data,Data}} ->
+ Data
+ after 2000 ->
+ pal("~p",[erlang:process_info(self())]),
+ exit(did_not_get_port_data)
+ end;
+handle_msg(get_data,_Port,Owner,{Data,Exit}) ->
+ pal("GetData",[]),
+ {hd(Data),Owner,{tl(Data),Exit}};
+handle_msg(get_exit,Port,_Owner,{_Data,[]}) ->
+ %% Wait for exit if it has not arrived yet
+ receive
+ {'EXIT',Port,Reason} ->
+ [{'EXIT',Reason}]
+ after 2000 ->
+ pal("~p",[erlang:process_info(self())]),
+ exit(did_not_get_port_exit)
+ end;
+handle_msg(get_exit,_Port,Owner,{Data,Exit}) ->
+ {hd(Exit),Owner,{Data,tl(Exit)}}.
+
+
+
+call(Pid,Msg) ->
+ pal("call(~p,~p)",[Pid,Msg]),
+ send(Pid,{call,Msg,self()}),
+ receive
+ Ret ->
+ Ret
+ end.
+ack(Pid,Msg) ->
+ pal("ack(~p,~p)",[Pid,Msg]),
+ send(Pid,{ack,Msg,self()}),
+ receive
+ Ret ->
+ Ret
+ end.
+
+cast(Pid,Msg) ->
+ pal("cast(~p,~p)",[Pid,Msg]),
+ send(Pid,{cast,Msg}).
+
+send(Pid,Msg) ->
+ erlang:send(Pid,Msg).
+send(Prt,Msg,Opts) ->
+ erlang:send(Prt,Msg,Opts).
+
+
+port_scheduling(Scenario,Validation,Path) ->
+ DrvName = "scheduling_drv",
+ erl_ddll:start(),
+ case erl_ddll:load_driver(Path, DrvName) of
+ ok -> ok;
+ {error, Error} ->
+ io:format("~s\n", [erl_ddll:format_error(Error)]),
+ ?line ?t:fail()
+ end,
+
+ Data = run_scenario(lists:flatten(Scenario),[{drvname,DrvName}]),
+ ok = validate_scenario(Data,Validation).
+
+
+run_scenario([{V,{Module,Cmd,Args}}|T],Vars) ->
+ Res = run_command(Module,Cmd,
+ replace_args(Args,Vars)),
+ run_scenario(T,[{V,Res}|Vars]);
+run_scenario([{V,{Cmd,Args}}|T],Vars) ->
+ run_scenario([{V,{?MODULE,Cmd,Args}}|T],Vars);
+run_scenario([],Vars) ->
+ Vars.
+
+run_command(_M,spawn,{Args,Opts}) ->
+ Pid = spawn_opt(fun() -> apply(?MODULE,process_init,Args) end,[link|Opts]),
+ pal("spawn(~p): ~p",[Args,Pid]),
+ Pid;
+run_command(M,spawn,Args) ->
+ run_command(M,spawn,{Args,[]});
+run_command(Mod,Func,Args) ->
+ erlang:display({{Mod,Func,Args},now()}),
+ apply(Mod,Func,Args).
+
+validate_scenario(Data,[{print,Var}|T]) ->
+ pal("Val: ~p",[proplists:get_value(Var,Data)]),
+ validate_scenario(Data,T);
+validate_scenario(Data,[{eq,Var,Value}|T]) ->
+ case proplists:get_value(Var,Data) of
+ Value ->
+ validate_scenario(Data,T);
+ Else ->
+ exit({eq_return,Value,Else})
+ end;
+validate_scenario(Data,[{neq,Var,Value}|T]) ->
+ case proplists:get_value(Var,Data) of
+ Value ->
+ exit({neq_return,Value});
+ _Else ->
+ validate_scenario(Data,T)
+ end;
+validate_scenario(Data,[{seq,Var,Seq}|T]) ->
+ try
+ validate_sequence(proplists:get_value(Var,Data),Seq)
+ catch _:{validate_sequence,NotFound} ->
+ exit({validate_sequence,NotFound,Data})
+ end,
+ validate_scenario(Data,T);
+validate_scenario(_,[]) ->
+ ok.
+
+validate_sequence(Data,Validation) when is_binary(Data) ->
+ validate_sequence(binary_to_list(Data),Validation);
+validate_sequence([H|R],[H|T]) ->
+ validate_sequence(R,T);
+validate_sequence([_|R],Seq) ->
+ validate_sequence(R,Seq);
+validate_sequence(_,[]) ->
+ ok;
+validate_sequence([],NotFound) ->
+ exit({validate_sequence,NotFound}).
+
+replace_args({var,Var},Vars) ->
+ proplists:get_value(Var,Vars);
+replace_args([H|T],Vars) ->
+ [replace_args(H,Vars)|replace_args(T,Vars)];
+replace_args([],_Vars) ->
+ [];
+replace_args(Tuple,Vars) when is_tuple(Tuple) ->
+ list_to_tuple(replace_args(tuple_to_list(Tuple),Vars));
+replace_args(Else,_Vars) ->
+ Else.
+
+pal(_F,_A) -> ok.
+%pal(Format,Args) ->
+% ct:pal("~p "++Format,[self()|Args]).
+% erlang:display(lists:flatten(io_lib:format("~p "++Format,[self()|Args]))).
+
+
%%% Utilities.
chk_range(Min, Val, Max) when Min =< Val, Val =< Max ->
diff --git a/erts/emulator/test/busy_port_SUITE_data/Makefile.src b/erts/emulator/test/busy_port_SUITE_data/Makefile.src
index 664909db71..b5fcf25176 100644
--- a/erts/emulator/test/busy_port_SUITE_data/Makefile.src
+++ b/erts/emulator/test/busy_port_SUITE_data/Makefile.src
@@ -17,9 +17,10 @@
# %CopyrightEnd%
#
-all: busy_drv@dll@ hard_busy_drv@dll@ soft_busy_drv@dll@
+all: busy_drv@dll@ hard_busy_drv@dll@ soft_busy_drv@dll@ scheduling_drv@dll@
@SHLIB_RULES@
hard_busy_drv@obj@: hard_busy_drv.c hs_busy_drv.c
soft_busy_drv@obj@: soft_busy_drv.c hs_busy_drv.c
+scheduling_drv@obj@: scheduling_drv.c
diff --git a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
index 9f6bd310c6..dcbaf500b8 100644
--- a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
+++ b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
@@ -71,9 +71,9 @@ void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
ERL_DRV_PID, driver_caller(port),
ERL_DRV_TUPLE, (ErlDrvTermData) 3
};
- res = driver_output_term(port, msg, sizeof(msg)/sizeof(ErlDrvTermData));
+ res = erl_drv_output_term(driver_mk_port(port), msg, sizeof(msg)/sizeof(ErlDrvTermData));
if (res <= 0)
- driver_failure_atom(port, "driver_output_term failed");
+ driver_failure_atom(port, "erl_drv_output_term failed");
}
ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
diff --git a/erts/emulator/test/busy_port_SUITE_data/scheduling_drv.c b/erts/emulator/test/busy_port_SUITE_data/scheduling_drv.c
new file mode 100644
index 0000000000..57be9b6392
--- /dev/null
+++ b/erts/emulator/test/busy_port_SUITE_data/scheduling_drv.c
@@ -0,0 +1,190 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifdef __WIN32__
+#include <windows.h>
+#else
+#include <sys/select.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include "erl_driver.h"
+
+#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \
+ (((unsigned char*) (s))[1] << 16) | \
+ (((unsigned char*) (s))[2] << 8) | \
+ (((unsigned char*) (s))[3]))
+
+#define ERTS_TEST_SCHEDULING_DRV_NAME "scheduling_drv"
+#define ERTS_TEST_SCHEDULING_DRV_FLAGS \
+ ERL_DRV_FLAG_USE_PORT_LOCKING | ERL_DRV_FLAG_SOFT_BUSY
+
+ErlDrvData start(ErlDrvPort port, char *command);
+void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
+void stop(ErlDrvData drv_data);
+void timeout(ErlDrvData drv_data);
+
+static void delay(unsigned ms);
+
+static ErlDrvEntry busy_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ output,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ ERTS_TEST_SCHEDULING_DRV_NAME,
+ NULL /* finish */,
+ NULL /* handle */,
+ control,
+ timeout,
+ NULL /* outputv */,
+ NULL /* ready_async */,
+ NULL /* flush */,
+ NULL /* call */,
+ NULL /* event */,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERTS_TEST_SCHEDULING_DRV_FLAGS,
+ NULL /* handle2 */,
+ NULL /* handle_monitor */,
+ NULL /* stop_select */
+};
+
+#define DBG(data,FMT)
+/* #define DBG(data,FMT) printf("0x%.8lx: %s",driver_caller(data->port),FMT); */
+
+typedef struct SchedDrvData {
+ ErlDrvPort port;
+ char data[255];
+ int curr;
+ int use_auto_busy;
+} SchedDrvData;
+
+DRIVER_INIT(busy_drv)
+{
+ return &busy_drv_entry;
+}
+
+ErlDrvData start(ErlDrvPort port, char *command)
+{
+ SchedDrvData *d = driver_alloc(sizeof(SchedDrvData));
+ d->port = port;
+ d->curr = 0;
+ d->use_auto_busy = 0;
+ DBG(d,"start\r\n");
+ return (ErlDrvData) d;
+}
+
+void stop(ErlDrvData drv_data) {
+ SchedDrvData *d = (SchedDrvData*)drv_data;
+ driver_output(d->port,d->data,d->curr);
+ DBG(d,"close\r\n");
+ driver_free(d);
+ return;
+}
+
+void timeout(ErlDrvData drv_data) {
+ SchedDrvData *d = (SchedDrvData*)drv_data;
+ set_busy_port(d->port, 0);
+ DBG(d,"timeout\r\n");
+}
+
+void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
+{
+ int res;
+ unsigned int command = *buf;
+ SchedDrvData *d = (SchedDrvData*)drv_data;
+
+ switch (command) {
+ case 'B': /* busy */
+ DBG(d,"busy: ");
+ set_busy_port(d->port, 1);
+ break;
+ case 'L': /* busy long call */
+ DBG(d,"long: ");
+ delay(buf[5]*100);
+ set_busy_port(d->port, 1);
+ break;
+ case 'D': /* delay call */
+ DBG(d,"delay: ");
+ delay(buf[5]*100);
+ break;
+ case 'N': /* not busy */
+ DBG(d,"not");
+ set_busy_port(d->port, 0);
+ goto done;
+ case 'C': /* change state */
+ DBG(d,"chang: ");
+ break;
+ case 'G': /* get state */
+ DBG(d,"get : ");
+ driver_output(d->port,d->data,d->curr);
+ return;
+ default:
+ driver_failure_posix((ErlDrvPort) drv_data, EINVAL);
+ break;
+ }
+ if (len > 1) {
+ unsigned int val = get_int32(buf+1);
+ fprintf(stderr,"%u",val);
+ d->data[d->curr++] = val;
+ }
+ done:
+ fprintf(stderr,"\r\n");
+}
+
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
+{
+ switch (command) {
+ case 'B': /* busy */
+ set_busy_port((ErlDrvPort) drv_data, 1);
+ break;
+ case 'N': /* not busy */
+ set_busy_port((ErlDrvPort) drv_data, 0);
+ break;
+ default:
+ driver_failure_posix((ErlDrvPort) drv_data, EINVAL);
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * Delays (sleeps) the given number of milli-seconds.
+ */
+
+static void delay(unsigned ms)
+{
+ fprintf(stderr,"delay(%u)",ms);
+#ifdef __WIN32__
+ Sleep(ms);
+#else
+ struct timeval t;
+ t.tv_sec = ms/1000;
+ t.tv_usec = (ms % 1000) * 1000;
+
+ select(0, NULL, NULL, NULL, &t);
+#endif
+}
diff --git a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
index c2086c5860..d72b20d143 100644
--- a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
@@ -56,6 +56,7 @@ static ErlDrvEntry async_blast_drv_entry = {
typedef struct {
ErlDrvPort port;
+ ErlDrvTermData port_id;
ErlDrvTermData caller;
int counter;
} async_blast_data_t;
@@ -81,6 +82,7 @@ static ErlDrvData start(ErlDrvPort port,
return ERL_DRV_ERROR_GENERAL;
abd->port = port;
+ abd->port_id = driver_mk_port(port);
abd->counter = 0;
return (ErlDrvData) abd;
}
@@ -97,12 +99,12 @@ static void ready_async(ErlDrvData drv_data,
async_blast_data_t *abd = (async_blast_data_t *) drv_data;
if (--abd->counter == 0) {
ErlDrvTermData spec[] = {
- ERL_DRV_PORT, driver_mk_port(abd->port),
+ ERL_DRV_PORT, abd->port_id,
ERL_DRV_ATOM, driver_mk_atom("done"),
ERL_DRV_TUPLE, 2
};
- driver_send_term(abd->port, abd->caller,
- spec, sizeof(spec)/sizeof(spec[0]));
+ erl_drv_send_term(abd->port_id, abd->caller,
+ spec, sizeof(spec)/sizeof(spec[0]));
}
}
diff --git a/erts/emulator/test/driver_SUITE_data/caller_drv.c b/erts/emulator/test/driver_SUITE_data/caller_drv.c
index 1ed20b0638..2731f9b317 100644
--- a/erts/emulator/test/driver_SUITE_data/caller_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/caller_drv.c
@@ -85,9 +85,9 @@ send_caller(ErlDrvData drv_data, char *func)
ERL_DRV_PID, driver_caller(port),
ERL_DRV_TUPLE, (ErlDrvTermData) 4
};
- res = driver_output_term(port, msg, sizeof(msg)/sizeof(ErlDrvTermData));
+ res = erl_drv_output_term(driver_mk_port(port), msg, sizeof(msg)/sizeof(ErlDrvTermData));
if (res <= 0)
- driver_failure_atom(port, "driver_output_term failed");
+ driver_failure_atom(port, "erl_drv_output_term failed");
}
static ErlDrvData
diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c
index 3da067fd09..81dfb65191 100644
--- a/erts/emulator/test/driver_SUITE_data/monitor_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c
@@ -117,7 +117,7 @@ static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor)
o->next = p->next;
}
driver_free(p);
- driver_send_term(data->port, data->ipid, spec, sizeof(spec)/sizeof(ErlDrvTermData));
+ erl_drv_send_term(driver_mk_port(data->port), data->ipid, spec, sizeof(spec)/sizeof(ErlDrvTermData));
}
return;
diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
index 221fd0ce51..93ef767d75 100644
--- a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
@@ -134,8 +134,8 @@ static void send_reply(Otp9302AsyncData *adata)
ERL_DRV_ATOM, adata->term_data.msg,
ERL_DRV_TUPLE, 2
};
- driver_send_term(adata->port, adata->term_data.receiver,
- spec, sizeof(spec)/sizeof(spec[0]));
+ erl_drv_send_term(adata->term_data.port, adata->term_data.receiver,
+ spec, sizeof(spec)/sizeof(spec[0]));
}
static void enqueue_reply(Otp9302AsyncData *adata)
diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
index 0c86a26604..cbee1c3dce 100644
--- a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
@@ -177,15 +177,16 @@ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data)
{
PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data;
if (dp->cmd == PEEK_NONXQ_WAIT) {
+ ErlDrvTermData port_id = driver_mk_port(dp->port);
ErlDrvTermData spec[] = {
- ERL_DRV_PORT, driver_mk_port(dp->port),
+ ERL_DRV_PORT, port_id,
ERL_DRV_ATOM, driver_mk_atom("test_successful"),
ERL_DRV_TUPLE, 2
};
- driver_send_term(dp->port,
- dp->caller,
- spec,
- sizeof(spec) / sizeof(spec[0]));
+ erl_drv_send_term(port_id,
+ dp->caller,
+ spec,
+ sizeof(spec) / sizeof(spec[0]));
}
if (thread_data)
driver_free(thread_data);
diff --git a/erts/emulator/test/driver_SUITE_data/thr_msg_blast_drv.c b/erts/emulator/test/driver_SUITE_data/thr_msg_blast_drv.c
index 1070678d7b..5a9112afa3 100644
--- a/erts/emulator/test/driver_SUITE_data/thr_msg_blast_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/thr_msg_blast_drv.c
@@ -168,8 +168,8 @@ static void *thread(void *varg)
for (s = 0; s < THR_MSG_BLAST_NO_SENDS_PER_PROC; s++) {
for (p = 0; p < THR_MSG_BLAST_NO_PROCS; p++) {
- int res = driver_send_term(tmbd->port, tmbd->proc[p],
- spec, sizeof(spec)/sizeof(spec[0]));
+ int res = erl_drv_send_term(tmbd->td_port, tmbd->proc[p],
+ spec, sizeof(spec)/sizeof(spec[0]));
if (p == 0 && res <= 0)
abort(); /* Could not send to creator */
}
diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
index b4542f3e36..2cd3209231 100644
--- a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
@@ -42,6 +42,7 @@
typedef struct {
TestCaseState_t visible;
ErlDrvPort port;
+ ErlDrvTermData port_id;
int result;
jmp_buf done_jmp_buf;
char *comment;
@@ -98,6 +99,7 @@ testcase_drv_start(ErlDrvPort port, char *command)
itcs->visible.testcase_name = testcase_name();
itcs->visible.extra = NULL;
itcs->port = port;
+ itcs->port_id = driver_mk_port(port);
itcs->result = TESTCASE_FAILED;
itcs->comment = "";
@@ -143,7 +145,7 @@ testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
msg[1] = (ErlDrvTermData) result_atom;
msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
+ msg[3] = itcs->port_id;
msg[4] = ERL_DRV_ATOM;
msg[5] = driver_mk_atom(itcs->visible.testcase_name);
@@ -155,7 +157,7 @@ testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
msg[9] = ERL_DRV_TUPLE;
msg[10] = (ErlDrvTermData) 4;
- driver_output_term(itcs->port, msg, 11);
+ erl_drv_output_term(itcs->port_id, msg, 11);
}
int
@@ -185,7 +187,7 @@ testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
msg[1] = (ErlDrvTermData) driver_mk_atom("print");
msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
+ msg[3] = itcs->port_id;
msg[4] = ERL_DRV_ATOM;
msg[5] = driver_mk_atom(itcs->visible.testcase_name);
@@ -197,7 +199,7 @@ testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
msg[9] = ERL_DRV_TUPLE;
msg[10] = (ErlDrvTermData) 4;
- driver_output_term(itcs->port, msg, 11);
+ erl_drv_output_term(itcs->port_id, msg, 11);
}
diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
index b3feca79f0..f8613487b0 100644
--- a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
+++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
@@ -664,7 +664,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count)
/* Signal end of test case */
msg[0] = ERL_DRV_NIL;
- driver_output_term(erlang_port, msg, 1);
+ erl_drv_output_term(driver_mk_port(erlang_port), msg, 1);
return;
}
break;
@@ -687,14 +687,14 @@ static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count)
static void output_term(ErlDrvTermData* msg, int len)
{
- if (driver_output_term(erlang_port, msg, len) <= 0) {
- driver_failure_atom(erlang_port, "driver_output_term_failed");
+ if (erl_drv_output_term(driver_mk_port(erlang_port), msg, len) <= 0) {
+ driver_failure_atom(erlang_port, "erl_drv_output_term_failed");
}
}
static void fail_term(ErlDrvTermData* msg, int len, int line)
{
- int status = driver_output_term(erlang_port, msg, len);
+ int status = erl_drv_output_term(driver_mk_port(erlang_port), msg, len);
if (status == 1) {
char buf[1024];
diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index b89a8c4a0e..1e0705fabe 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -874,7 +874,7 @@ exception_test(Opts, Func0, Args0) ->
%% wrap them in wrappers...
?line {Func1,Args1} =
case Function of
- true -> {fun (F, As) -> exc(F, As) end,[Func0,Args0]};
+ true -> {fun exc/2,[Func0,Args0]};
false -> {Func0,Args0}
end,
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 50c61f50eb..d865164bb0 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -124,6 +124,7 @@ static char *pluss_val_switches[] = {
"bwt",
"cl",
"ct",
+ "tbt",
"wt",
"ws",
"ss",
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index bea586b11c..af7adc2d44 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 061db72dd8..e966ac5296 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -2057,6 +2057,8 @@ tuple_to_list(_Tuple) ->
(multi_scheduling) -> disabled | blocked | enabled;
(multi_scheduling_blockers) -> [PID :: pid()];
(otp_release) -> string();
+ (port_count) -> non_neg_integer();
+ (port_limit) -> pos_integer();
(process_count) -> pos_integer();
(process_limit) -> pos_integer();
(procs) -> binary();
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 405df1e978..796a0832d7 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -64,7 +64,7 @@ end_per_testcase(TestCase, Config) ->
suite() ->
- [{timetrap,{seconds,20}}].
+ [{timetrap,{minutes,1}}].
all() ->
all(suite).
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 56a343a96f..b89d7d4dc5 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -154,6 +154,9 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config) ->
{init,NodeName,[
{node_start,[{startup_functions,[]},
{monitor_master,true},
+ {boot_timeout,10},
+ {init_timeout,10},
+ {startup_timeout,10},
{env,Env}]},
{eval,{erlang,nodes,[]}}]
}
diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl
index 3042a924fe..c89a4cdabe 100644
--- a/lib/common_test/test/ct_netconfc_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE.erl
@@ -43,12 +43,11 @@
%% there will be clashes with logging processes etc).
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config1 = ct_test_support:init_per_suite(Config),
case application:load(crypto) of
- {error,Reason} ->
+ {error,Reason} when Reason=/={already_loaded,crypto} ->
{skip, Reason};
_ ->
- Config1
+ ct_test_support:init_per_suite(Config)
end.
end_per_suite(Config) ->
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index d337158bce..54526e8e83 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -1044,12 +1044,9 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
Key = gen_dsa2(LSize, NSize),
{Key, encode_key(Key)}.
-encode_key(Key = #'RSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
+ Der = public_key:der_encode('DSAPrivateKey', Key),
+ {'DSAPrivateKey', Der, not_encrypted}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index fc572aa82f..8814570e99 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -1043,8 +1043,8 @@ result_match({SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,'_'}}}},
true;
result_match({failed,{timetrap_timeout,{'$approx',Num}}},
{failed,{timetrap_timeout,Value}}) ->
- if Value >= trunc(Num-0.02*Num),
- Value =< trunc(Num+0.02*Num) -> true;
+ if Value >= trunc(Num-0.05*Num),
+ Value =< trunc(Num+0.05*Num) -> true;
true -> false
end;
result_match({user_timetrap_error,{Why,'_'}},
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index ff6c7c11dc..531968b3c8 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -138,17 +138,7 @@ string(Str, Dict) when is_list(Str) ->
-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, 0, #asm{lambdas=Lambdas0}=Dict) ->
- case lists:keyfind(Lbl, 1, Lambdas0) of
- {Lbl,{OldIndex,_,_,_,_}} ->
- {OldIndex,Dict};
- false ->
- new_lambda(Lbl, 0, Dict)
- end;
-lambda(Lbl, NumFree, Dict) ->
- new_lambda(Lbl, NumFree, Dict).
-
-new_lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
%% Set Index the same as OldIndex.
Index = OldIndex,
@@ -245,12 +235,10 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{exports=Ext0,locals=Loc0,lambdas=Lambdas0}) ->
+lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
- Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]),
- All = sofs:union(Loc, Ext),
- Lambdas2 = sofs:relative_product1(Lambdas1, All),
+ Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
{{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
{length(Lambdas),Lambdas}.
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index f17b0bd130..fbd7452301 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2672,16 +2672,19 @@ bsm_nonempty([#c_clause{pats=Ps}|Cs], Pos) ->
bsm_nonempty([], _ ) -> false.
%% bsm_ensure_no_partition(Cs, Pos) -> ok (exception if problem)
-%% We must make sure that binary matching is not partitioned between
+%% We must make sure that matching is not partitioned between
%% variables like this:
%% foo(<<...>>) -> ...
-%% foo(Var) when ... -> ...
-%% foo(<<...>>) ->
+%% foo(<Variable>) when ... -> ...
+%% foo(<Any non-variable pattern>) ->
%% If there is such partition, we are not allowed to reuse the binary variable
-%% for the match context. Also, arguments to the left of the argument that
-%% is matched against a binary, are only allowed to be simple variables, not
-%% used in guards. The reason is that we must know that the binary is only
-%% matched in one place.
+%% for the match context.
+%%
+%% Also, arguments to the left of the argument that is matched
+%% against a binary, are only allowed to be simple variables, not
+%% used in guards. The reason is that we must know that the binary is
+%% only matched in one place (i.e. there must be only one bs_start_match2
+%% instruction emitted).
bsm_ensure_no_partition(Cs, Pos) ->
bsm_ensure_no_partition_1(Cs, Pos, before).
@@ -2689,6 +2692,12 @@ bsm_ensure_no_partition(Cs, Pos) ->
%% Loop through each clause.
bsm_ensure_no_partition_1([#c_clause{pats=Ps,guard=G}|Cs], Pos, State0) ->
State = bsm_ensure_no_partition_2(Ps, Pos, G, simple_vars, State0),
+ case State of
+ 'after' ->
+ bsm_ensure_no_partition_after(Cs, Pos);
+ _ ->
+ ok
+ end,
bsm_ensure_no_partition_1(Cs, Pos, State);
bsm_ensure_no_partition_1([], _, _) -> ok.
@@ -2698,8 +2707,7 @@ bsm_ensure_no_partition_2([#c_binary{}=Where|_], 1, _, Vstate, State) ->
before when Vstate =:= simple_vars -> within;
before -> bsm_problem(Where, Vstate);
within when Vstate =:= simple_vars -> within;
- within -> bsm_problem(Where, Vstate);
- 'after' -> bsm_problem(Where, bin_partition)
+ within -> bsm_problem(Where, Vstate)
end;
bsm_ensure_no_partition_2([#c_alias{}=Alias|_], 1, N, Vstate, State) ->
%% Retrieve the real pattern that the alias refers to and check that.
@@ -2748,6 +2756,15 @@ bsm_ensure_no_partition_2([#c_var{name=V}|Ps], N, G, Vstate, S) ->
bsm_ensure_no_partition_2([_|Ps], N, G, _, S) ->
bsm_ensure_no_partition_2(Ps, N-1, G, bin_argument_order, S).
+bsm_ensure_no_partition_after([#c_clause{pats=Ps}|Cs], Pos) ->
+ case nth(Pos, Ps) of
+ #c_var{} ->
+ bsm_ensure_no_partition_after(Cs, Pos);
+ P ->
+ bsm_problem(P, bin_partition)
+ end;
+bsm_ensure_no_partition_after([], _) -> ok.
+
bsm_could_match_binary(#c_alias{pat=P}) -> bsm_could_match_binary(P);
bsm_could_match_binary(#c_cons{}) -> false;
bsm_could_match_binary(#c_tuple{}) -> false;
@@ -2872,7 +2889,7 @@ format_error(useless_building) ->
format_error(bin_opt_alias) ->
"INFO: the '=' operator will prevent delayed sub binary optimization";
format_error(bin_partition) ->
- "INFO: non-consecutive clauses that match binaries "
+ "INFO: matching non-variables after a previous clause matching a variable "
"will prevent delayed sub binary optimization";
format_error(bin_left_var_used_in_guard) ->
"INFO: a variable to the left of the binary pattern is used in a guard; "
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index b1bff47f69..8ef71e1346 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -235,8 +235,16 @@ gexpr_test_add(Ke, St0) ->
%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
%% Convert a Core expression, flattening it at the same time.
-expr(#c_var{anno=A,name={Name,Arity}}, Sub, St) ->
- {#k_local{anno=A,name=get_fsub(Name, Arity, Sub),arity=Arity},[],St};
+expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
+ %% A local in an expression.
+ %% For now, these are wrapped into a fun by reverse
+ %% etha-conversion, but really, there should be exactly one
+ %% such "lambda function" for each escaping local name,
+ %% instead of one for each occurrence as done now.
+ Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
+ V <- integers(1, Arity)],
+ Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
+ expr(Fun, Sub, St);
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
expr(#c_literal{anno=A,val=V}, _Sub, St) ->
@@ -1655,19 +1663,6 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
#k_int{val=Index},#k_int{val=Uniq}|Fvs],
ret=Rs},
Free,add_local_function(Fun, St)};
-uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) ->
- Fs = get_free(Name, Arity, St),
- FsCount = length(Fs),
- Free = lit_list_vars(Fs),
- %% Set dummy values for Index and Uniq -- the real values will
- %% be assigned by beam_asm.
- Index = Uniq = 0,
- Bif = #k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
- op=#k_internal{name=make_fun,arity=FsCount+3},
- args=[#k_atom{val=Name},#k_int{val=FsCount+Arity},
- #k_int{val=Index},#k_int{val=Uniq}|Fs],
- ret=Rs},
- {Bif,Free,St};
uexpr(Lit, {break,Rs0}, St0) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
@@ -1848,6 +1843,12 @@ make_list(Es) ->
#c_cons{hd=E,tl=Acc}
end, #c_literal{val=[]}, Es).
+%% List of integers in interval [N,M]. Empty list if N > M.
+
+integers(N, M) when N =< M ->
+ [N|integers(N + 1, M)];
+integers(_, _) -> [].
+
%% is_in_guard(State) -> true|false.
is_in_guard(#kern{guard_refc=Refc}) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index d63d2235d7..e8a92c509e 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -33,7 +33,8 @@
matching_meets_construction/1,simon/1,matching_and_andalso/1,
otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1,
match_string/1,zero_width/1,bad_size/1,haystack/1,
- cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1]).
+ cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1,
+ no_partition/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -57,7 +58,8 @@ groups() ->
matching_meets_construction,simon,
matching_and_andalso,otp_7188,otp_7233,otp_7240,
otp_7498,match_string,zero_width,bad_size,haystack,
- cover_beam_bool,matched_out_size,follow_fail_branch]}].
+ cover_beam_bool,matched_out_size,follow_fail_branch,
+ no_partition]}].
init_per_suite(Config) ->
@@ -1133,6 +1135,48 @@ ffb_2(<<_,T/bitstring>>, List, A) ->
[_|_] -> bit_size(T)
end.
+no_partition(_) ->
+ one = no_partition_1(<<"string">>, a1),
+ {two,<<"string">>} = no_partition_1(<<"string">>, a2),
+ {two,<<>>} = no_partition_1(<<>>, a2),
+ {two,a} = no_partition_1(a, a2),
+ three = no_partition_1(undefined, a3),
+ {four,a,[]} = no_partition_1([a], a4),
+ {five,a,b} = no_partition_1({a,b}, a5),
+
+ one = no_partition_2(<<"string">>, a1),
+ two = no_partition_2(<<"string">>, a2),
+ two = no_partition_2(<<>>, a2),
+ two = no_partition_2(a, a2),
+ three = no_partition_2(undefined, a3),
+ four = no_partition_2(42, a4),
+ five = no_partition_2([], a5),
+ six = no_partition_2(42.0, a6),
+ ok.
+
+no_partition_1(<<"string">>, a1) ->
+ one;
+no_partition_1(V, a2) ->
+ {two,V};
+no_partition_1(undefined, a3) ->
+ three;
+no_partition_1([H|T], a4) ->
+ {four,H,T};
+no_partition_1({A,B}, a5) ->
+ {five,A,B}.
+
+no_partition_2(<<"string">>, a1) ->
+ one;
+no_partition_2(_, a2) ->
+ two;
+no_partition_2(undefined, a3) ->
+ three;
+no_partition_2(42, a4) ->
+ four;
+no_partition_2([], a5) ->
+ five;
+no_partition_2(42.0, a6) ->
+ six.
check(F, R) ->
R = F().
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 0b932d5a1f..157c951f77 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -254,14 +254,35 @@ check_extraneous([C|Cs], SuccType) ->
end.
check_extraneous_1(Contract, SuccType) ->
- CRngs = erl_types:t_elements(erl_types:t_fun_range(Contract)),
+ CRng = erl_types:t_fun_range(Contract),
+ CRngs = erl_types:t_elements(CRng),
STRng = erl_types:t_fun_range(SuccType),
?debug("CR = ~p\nSR = ~p\n", [CRngs, STRng]),
- case [CR || CR <- CRngs, erl_types:t_is_none(erl_types:t_inf(CR, STRng, opaque))] of
- [] -> ok;
+ case [CR || CR <- CRngs,
+ erl_types:t_is_none(erl_types:t_inf(CR, STRng, opaque))] of
+ [] ->
+ CRngList = list_part(CRng),
+ STRngList = list_part(STRng),
+ case is_not_nil_list(CRngList) andalso is_not_nil_list(STRngList) of
+ false -> ok;
+ true ->
+ CRngElements = erl_types:t_list_elements(CRngList),
+ STRngElements = erl_types:t_list_elements(STRngList),
+ Inf = erl_types:t_inf(CRngElements, STRngElements, opaque),
+ case erl_types:t_is_none(Inf) of
+ true -> {error, invalid_contract};
+ false -> ok
+ end
+ end;
CRs -> {error, {extra_range, erl_types:t_sup(CRs), STRng}}
end.
+list_part(Type) ->
+ erl_types:t_inf(erl_types:t_list(), Type, opaque).
+
+is_not_nil_list(Type) ->
+ erl_types:t_is_list(Type) andalso not erl_types:t_is_nil(Type).
+
%% This is the heart of the "range function"
-spec process_contracts([contract_pair()], [erl_types:erl_type()]) -> erl_types:erl_type().
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl
index b4f03fab03..17cc9a953d 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl
@@ -1806,7 +1806,6 @@ system_info2(dump_log_update_in_place) ->
system_info2(dump_log_update_in_place) ->
mnesia_monitor:get_env(dump_log_update_in_place);
system_info2(max_wait_for_decision) -> mnesia_monitor:get_env(max_wait_for_decision);
-system_info2(embedded_mnemosyne) -> mnesia_monitor:get_env(embedded_mnemosyne);
system_info2(ignore_fallback_at_startup) -> mnesia_monitor:get_env(ignore_fallback_at_startup);
system_info2(fallback_error_function) -> mnesia_monitor:get_env(fallback_error_function);
system_info2(log_version) -> mnesia_log:version();
@@ -1840,7 +1839,6 @@ system_info_items(yes) ->
dump_log_time_threshold,
dump_log_update_in_place,
dump_log_write_threshold,
- embedded_mnemosyne,
event_module,
extra_db_nodes,
fallback_activated,
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl
index b64419d5a8..a1c25b5120 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl
@@ -631,7 +631,6 @@ env() ->
dump_log_time_threshold,
dump_log_update_in_place,
dump_log_write_threshold,
- embedded_mnemosyne,
event_module,
extra_db_nodes,
ignore_fallback_at_startup,
@@ -660,8 +659,6 @@ default_env(dump_log_update_in_place) ->
true;
default_env(dump_log_write_threshold) ->
1000;
-default_env(embedded_mnemosyne) ->
- false;
default_env(event_module) ->
mnesia_event;
default_env(extra_db_nodes) ->
@@ -703,7 +700,6 @@ do_check_type(event_module, A) when atom(A) -> A;
do_check_type(ignore_fallback_at_startup, B) -> bool(B);
do_check_type(fallback_error_function, {Mod, Func})
when atom(Mod), atom(Func) -> {Mod, Func};
-do_check_type(embedded_mnemosyne, B) -> bool(B);
do_check_type(extra_db_nodes, L) when list(L) ->
Fun = fun(N) when N == node() -> false;
(A) when atom(A) -> true
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl
index 78609ffdde..970e0e5f47 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl
@@ -57,9 +57,8 @@ init() ->
Event = event_procs(),
Kernel = kernel_procs(),
- Mnemosyne = mnemosyne_procs(),
- {ok, {Flags, Event ++ Kernel ++ Mnemosyne}}.
+ {ok, {Flags, Event ++ Kernel}}.
event_procs() ->
KillAfter = timer:seconds(30),
@@ -72,16 +71,6 @@ kernel_procs() ->
KA = infinity,
[{K, {K, start, []}, permanent, KA, supervisor, [K, supervisor]}].
-mnemosyne_procs() ->
- case mnesia_monitor:get_env(embedded_mnemosyne) of
- true ->
- Q = mnemosyne_sup,
- KA = infinity,
- [{Q, {Q, start, []}, permanent, KA, supervisor, [Q, supervisor]}];
- false ->
- []
- end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% event handler
@@ -107,11 +96,8 @@ add_event_handler() ->
kill() ->
Mnesia = [mnesia_fallback | mnesia:ms()],
- Mnemosyne = mnemosyne_ms(),
Kill = fun(Name) -> catch exit(whereis(Name), kill) end,
- lists:foreach(Kill, Mnemosyne),
lists:foreach(Kill, Mnesia),
- lists:foreach(fun ensure_dead/1, Mnemosyne),
lists:foreach(fun ensure_dead/1, Mnesia),
timer:sleep(10),
case lists:keymember(mnesia, 1, application:which_applications()) of
@@ -128,9 +114,3 @@ ensure_dead(Name) ->
timer:sleep(10),
ensure_dead(Name)
end.
-
-mnemosyne_ms() ->
- case mnesia_monitor:get_env(embedded_mnemosyne) of
- true -> mnemosyne:ms();
- false -> []
- end.
diff --git a/lib/dialyzer/test/small_SUITE_data/results/empty_list_infimum b/lib/dialyzer/test/small_SUITE_data/results/empty_list_infimum
new file mode 100644
index 0000000000..6eaf60b91d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/empty_list_infimum
@@ -0,0 +1,2 @@
+
+empty_list_infimum.erl:38: Invalid type specification for function empty_list_infimum:list_vhost_permissions/1. The success typing is (_) -> [[{_,_}]] \ No newline at end of file
diff --git a/lib/dialyzer/test/small_SUITE_data/src/empty_list_infimum.erl b/lib/dialyzer/test/small_SUITE_data/src/empty_list_infimum.erl
new file mode 100644
index 0000000000..b58fa732cb
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/empty_list_infimum.erl
@@ -0,0 +1,57 @@
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is VMware, Inc.
+%%
+
+-module(empty_list_infimum).
+
+-record(permission, {configure, write, read}).
+-record(user_vhost, {username, virtual_host}).
+-record(user_permission, {user_vhost, permission}).
+
+%%----------------------------------------------------------------------------
+
+-export([i_delete/1]).
+
+-type(vhost() :: binary()).
+
+-type(info_key() :: atom()).
+-type(info_keys() :: [info_key()]).
+
+-type(info() :: {info_key(), any()}).
+-type(infos() :: [info()]).
+
+%%----------------------------------------------------------------------------
+
+-spec i_delete(vhost()) -> 'ok'.
+
+i_delete(VHostPath) ->
+ [ok || _ <- list_vhost_permissions(VHostPath)],
+ ok.
+
+%%----------------------------------------------------------------------------
+
+vhost_perms_info_keys() ->
+ [user, configure, write, read].
+
+-spec list_vhost_permissions(vhost()) -> infos().
+
+list_vhost_permissions(VHostPath) ->
+ list_permissions(vhost_perms_info_keys(), rabbit_foo:some_list()).
+
+filter_props(Keys, Props) ->
+ [T || T = {K, _} <- Props, lists:member(K, Keys)].
+
+list_permissions(Keys, SomeList) ->
+ [filter_props(Keys, [{user, Username},
+ {vhost, VHostPath},
+ {configure, ConfigurePerm},
+ {write, WritePerm},
+ {read, ReadPerm}]) ||
+ #user_permission{user_vhost = #user_vhost{username = Username,
+ virtual_host = VHostPath},
+ permission = #permission{configure = ConfigurePerm,
+ write = WritePerm,
+ read = ReadPerm}} <-
+ SomeList].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/unknown_arity_function_spec.erl b/lib/dialyzer/test/small_SUITE_data/src/unknown_arity_function_spec.erl
new file mode 100644
index 0000000000..c7d7459614
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/unknown_arity_function_spec.erl
@@ -0,0 +1,10 @@
+-module(unknown_arity_function_spec).
+
+-export([test/2]).
+
+%-type t() :: 42 | fun((...) -> t()).
+%-type f() :: fun((...) -> 42).
+
+-spec test(fun((...) -> 42), list()) -> 42.
+test(F, L) ->
+ 42 = apply(F, L).
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
index 04dad2eee7..bd6f00af1f 100644
--- a/lib/eldap/doc/src/eldap.xml
+++ b/lib/eldap/doc/src/eldap.xml
@@ -68,7 +68,7 @@ filter() See present/1, substrings/2,
<fsummary>Open a connection to an LDAP server.</fsummary>
<type>
<v>Handle = handle()</v>
- <v>Option = {port, integer()} | {log, function()} | {timeout, integer()} | {ssl, boolean()}</v>
+ <v>Option = {port, integer()} | {log, function()} | {timeout, integer()} | {ssl, boolean()} | {sslopts, list()}</v>
</type>
<desc>
<p>Setup a connection to an LDAP server, the <c>HOST</c>'s are tried in order.</p>
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 5753cc4749..d030408770 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -42,7 +42,8 @@
log, % User provided log function
timeout = infinity, % Request timeout
anon_auth = false, % Allow anonymous authentication
- use_tls = false % LDAP/LDAPS
+ use_tls = false, % LDAP/LDAPS
+ tls_opts = [] % ssl:ssloptsion()
}).
%%% For debug purposes
@@ -353,6 +354,10 @@ parse_args([{ssl, true}|T], Cpid, Data) ->
parse_args(T, Cpid, Data#eldap{use_tls = true});
parse_args([{ssl, _}|T], Cpid, Data) ->
parse_args(T, Cpid, Data);
+parse_args([{sslopts, Opts}|T], Cpid, Data) when is_list(Opts) ->
+ parse_args(T, Cpid, Data#eldap{use_tls = true, tls_opts = Opts ++ Data#eldap.tls_opts});
+parse_args([{sslopts, _}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data);
parse_args([{log, F}|T], Cpid, Data) when is_function(F) ->
parse_args(T, Cpid, Data#eldap{log = F});
parse_args([{log, _}|T], Cpid, Data) ->
@@ -384,8 +389,8 @@ try_connect([],_) ->
do_connect(Host, Data, Opts) when Data#eldap.use_tls == false ->
gen_tcp:connect(Host, Data#eldap.port, Opts, Data#eldap.timeout);
do_connect(Host, Data, Opts) when Data#eldap.use_tls == true ->
- ssl:connect(Host, Data#eldap.port, [{verify,0}|Opts]).
-
+ SslOpts = [{verify,0} | Opts ++ Data#eldap.tls_opts],
+ ssl:connect(Host, Data#eldap.port, SslOpts).
loop(Cpid, Data) ->
receive
diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd
index c1237766e1..93592607df 100644
--- a/lib/erl_docgen/priv/dtd/common.refs.dtd
+++ b/lib/erl_docgen/priv/dtd/common.refs.dtd
@@ -26,10 +26,12 @@
<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
<!ELEMENT funcs (func)+ >
-<!ELEMENT func (name+,type_desc+,fsummary,type?,desc?) >
+<!ELEMENT func (name+,type_desc*,fsummary,type?,desc?) >
<!-- ELEMENT name is defined in each ref dtd -->
<!ELEMENT fsummary (#PCDATA|c|em)* >
-<!ELEMENT type (v,d?)+ >
+<!ELEMENT type (v,d?)* >
+<!ATTLIST type variable CDATA #IMPLIED
+ name_i CDATA #IMPLIED>
<!ELEMENT v (#PCDATA) >
<!ELEMENT d (#PCDATA|c|em)* >
<!ELEMENT desc (%block;|quote|br|marker|warning|note|anno)* >
@@ -41,3 +43,4 @@
<!ELEMENT datatypes (datatype)+ >
<!ELEMENT datatype (name+,desc?) >
<!ELEMENT type_desc (#PCDATA) >
+<!ATTLIST type_desc variable CDATA #REQUIRED>
diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd
index 9905086ff4..0cc5cfa06d 100644
--- a/lib/erl_docgen/priv/dtd/erlref.dtd
+++ b/lib/erl_docgen/priv/dtd/erlref.dtd
@@ -29,3 +29,6 @@
<!-- `name' is used in common.refs.dtd and must therefore
be defined in each *ref. dtd -->
<!ELEMENT name (#PCDATA) >
+<!ATTLIST name name CDATA #IMPLIED
+ arity CDATA #IMPLIED
+ clause_i CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index 7de5af2a49..c846bdbf34 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -1102,11 +1102,13 @@
<xsl:template match="taglist/item">
<xsl:param name="partnum"/>
- <fo:block xsl:use-attribute-sets="tagitem">
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
- </fo:block>
+ <fo:block-container>
+ <fo:block xsl:use-attribute-sets="tagitem">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
+ </fo:block-container>
</xsl:template>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 2599dc0ff7..a2262198dc 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1,2 +1 @@
-ERL_DOCGEN_VSN = 0.3.3
-
+ERL_DOCGEN_VSN = 0.3.4
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 98d65abba1..d93ad10bd4 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -765,7 +765,6 @@ type(erlang, node, 0, _) -> t_node();
%% Guard bif, needs to be here.
type(erlang, node, 1, Xs) ->
strict(arg_types(erlang, node, 1), Xs, fun (_) -> t_node() end);
-type(erlang, nodes, 0, _) -> t_list(t_node());
%% Guard bif, needs to be here.
type(erlang, round, 1, Xs) ->
strict(arg_types(erlang, round, 1), Xs, fun (_) -> t_integer() end);
@@ -2250,8 +2249,6 @@ arg_types(erlang, node, 0) ->
%% Guard bif, needs to be here.
arg_types(erlang, node, 1) ->
[t_identifier()];
-arg_types(erlang, nodes, 0) ->
- [];
%% Guard bif, needs to be here.
arg_types(erlang, round, 1) ->
[t_number()];
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index f5be8fb08f..ea1e7b1292 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -3566,7 +3566,7 @@ t_from_form({type, _L, function, []}, _TypeNames, _InOpaque, _RecDict,
t_from_form({type, _L, 'fun', []}, _TypeNames, _InOpaque, _RecDict,
_VarDict) ->
{t_fun(), []};
-t_from_form({type, _L, 'fun', [{type, _, any, []}, Range]}, TypeNames,
+t_from_form({type, _L, 'fun', [{type, _, any}, Range]}, TypeNames,
InOpaque, RecDict, VarDict) ->
{T, R} = t_from_form(Range, TypeNames, InOpaque, RecDict, VarDict),
{t_fun(T), R};
@@ -3909,7 +3909,7 @@ t_form_to_string({type, _L, binary, [Base, Unit]} = Type) ->
_ -> io_lib:format("Badly formed bitstr type ~w", [Type])
end;
t_form_to_string({type, _L, 'fun', []}) -> "fun()";
-t_form_to_string({type, _L, 'fun', [{type, _, any, []}, Range]}) ->
+t_form_to_string({type, _L, 'fun', [{type, _, any}, Range]}) ->
"fun(...) -> " ++ t_form_to_string(Range);
t_form_to_string({type, _L, 'fun', [{type, _, product, Domain}, Range]}) ->
"fun((" ++ string:join(t_form_to_string_list(Domain), ",") ++ ") -> "
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index e30ade1bd2..4a9b7d2ceb 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2012</year>
+ <year>1996</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -100,7 +100,11 @@
<name name="deep_list"/>
</datatype>
<datatype>
- <name name="fd"/>
+ <name><marker id="type-fd">fd()</marker></name>
+ <desc>
+ <p>A file descriptor representing a file opened in <seealso
+ marker="#raw">raw</seealso> mode.</p>
+ </desc>
</datatype>
<datatype>
<name name="filename"/>
@@ -109,8 +113,8 @@
<name name="io_device"/>
<desc>
<p>As returned by
- <seealso marker="#open/2">file:open/2</seealso>,
- a process handling I/O-protocols.</p>
+ <seealso marker="#open/2">file:open/2</seealso>;
+ <c>pid()</c> is a process handling I/O-protocols.</p>
</desc>
</datatype>
<datatype>
@@ -662,7 +666,8 @@
</item>
<tag><c>raw</c></tag>
<item>
- <p>The <c>raw</c> option allows faster access to a file,
+ <p><marker id="raw"/>
+ The <c>raw</c> option allows faster access to a file,
because no Erlang process is needed to handle the file.
However, a file opened in this way has the following
limitations:</p>
@@ -1251,11 +1256,11 @@
<p>The record <c>file_info</c> contains the following fields.</p>
<taglist>
- <tag><c>size = integer()</c></tag>
+ <tag><c>size = integer() >= 0</c></tag>
<item>
<p>Size of file in bytes.</p>
</item>
- <tag><c>type = device | directory | regular | other</c></tag>
+ <tag><c>type = device | directory | other | regular | symlink</c></tag>
<item>
<p>The type of the file.</p>
</item>
@@ -1263,22 +1268,22 @@
<item>
<p>The current system access to the file.</p>
</item>
- <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag>
<item>
<p>The last time the file was read.</p>
</item>
- <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag>
<item>
<p>The last time the file was written.</p>
</item>
- <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >=0</c></tag>
<item>
<p>The interpretation of this time field depends on
the operating system. On Unix, it is the last time
the file or the inode was changed. In Windows, it is
the create time.</p>
</item>
- <tag><c>mode = integer()</c></tag>
+ <tag><c>mode = integer() >= 0</c></tag>
<item>
<p>The file permissions as the sum of the following bit
values:</p>
@@ -1309,33 +1314,33 @@
<p>On Unix platforms, other bits than those listed above
may be set.</p>
</item>
- <tag><c>links = integer()</c></tag>
+ <tag><c>links = integer() >= 0</c></tag>
<item>
<p>Number of links to the file (this will always be 1 for
file systems which have no concept of links).</p>
</item>
- <tag><c>major_device = integer()</c></tag>
+ <tag><c>major_device = integer() >= 0</c></tag>
<item>
<p>Identifies the file system where the file is located.
In Windows, the number indicates a drive as follows:
0 means A:, 1 means B:, and so on.</p>
</item>
- <tag><c>minor_device = integer()</c></tag>
+ <tag><c>minor_device = integer() >= 0</c></tag>
<item>
<p>Only valid for character devices on Unix. In all other
cases, this field is zero.</p>
</item>
- <tag><c>inode = integer()</c></tag>
+ <tag><c>inode = integer() >= 0</c></tag>
<item>
<p>Gives the <c>inode</c> number. On non-Unix file systems,
this field will be zero.</p>
</item>
- <tag><c>uid = integer()</c></tag>
+ <tag><c>uid = integer() >= 0</c></tag>
<item>
<p>Indicates the owner of the file. Will be zero for
non-Unix file systems.</p>
</item>
- <tag><c>gid = integer()</c></tag>
+ <tag><c>gid = integer() >= 0</c></tag>
<item>
<p>Gives the group that the owner of the file belongs to.
Will be zero for non-Unix file systems.</p>
@@ -1766,22 +1771,22 @@
<p>The following fields are used from the record, if they are
given.</p>
<taglist>
- <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag>
<item>
<p>The last time the file was read.</p>
</item>
- <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag>
<item>
<p>The last time the file was written.</p>
</item>
- <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag>
<item>
<p>On Unix, any value give for this field will be ignored
(the "ctime" for the file will be set to the current
time). On Windows, this field is the new creation time to
set for the file.</p>
</item>
- <tag><c>mode = integer()</c></tag>
+ <tag><c>mode = integer() >= 0</c></tag>
<item>
<p>The file permissions as the sum of the following bit
values:</p>
@@ -1812,15 +1817,15 @@
<p>On Unix platforms, other bits than those listed above
may be set.</p>
</item>
- <tag><c>uid = integer()</c></tag>
+ <tag><c>uid = integer() >= 0</c></tag>
<item>
<p>Indicates the owner of the file. Ignored for non-Unix
file systems.</p>
</item>
- <tag><c>gid = integer()</c></tag>
+ <tag><c>gid = integer() >= 0</c></tag>
<item>
<p>Gives the group that the owner of the file belongs to.
- Ignored non-Unix file systems.</p>
+ Ignored for non-Unix file systems.</p>
</item>
</taglist>
<p>Typical error reasons:</p>
diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl
index bf97173122..69aec1ee36 100644
--- a/lib/kernel/include/file.hrl
+++ b/lib/kernel/include/file.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,32 +22,37 @@
%%--------------------------------------------------------------------------
-record(file_info,
- {size :: non_neg_integer(), % Size of file in bytes.
- type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
- access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time() | integer(), % The local time the file was last read:
- % {{Year, Mon, Day}, {Hour, Min, Sec}}.
- % atime, ctime, mtime may also be unix epochs()
- mtime :: file:date_time() | integer(), % The local time the file was last written.
- ctime :: file:date_time() | integer(), % The interpretation of this time field
- % is dependent on operating system.
- % On Unix it is the last time the file
- % or the inode was changed. On Windows,
- % it is the creation time.
- mode :: integer(), % File permissions. On Windows,
- % the owner permissions will be
- % duplicated for group and user.
- links :: non_neg_integer(), % Number of links to the file (1 if the
- % filesystem doesn't support links).
- major_device :: integer(), % Identifies the file system (Unix),
- % or the drive number (A: = 0, B: = 1)
- % (Windows).
- %% The following are Unix specific.
- %% They are set to zero on other operating systems.
- minor_device :: integer(), % Only valid for devices.
- inode :: integer(), % Inode number for file.
- uid :: integer(), % User id for owner.
- gid :: integer()}). % Group id for owner.
+ {size :: non_neg_integer(), % Size of file in bytes.
+ type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
+ access :: 'read' | 'write' | 'read_write' | 'none',
+ atime :: file:date_time() | non_neg_integer(),
+ % The local time the file was last read:
+ % {{Year, Mon, Day}, {Hour, Min, Sec}}.
+ % atime, ctime, mtime may also be unix epochs()
+ mtime :: file:date_time() | non_neg_integer(),
+ % The local time the file was last written.
+ ctime :: file:date_time() | non_neg_integer(),
+ % The interpretation of this time field
+ % is dependent on operating system.
+ % On Unix it is the last time the file
+ % or the inode was changed. On Windows,
+ % it is the creation time.
+ mode :: non_neg_integer(), % File permissions. On Windows,
+ % the owner permissions will be
+ % duplicated for group and user.
+ links :: non_neg_integer(),
+ % Number of links to the file (1 if the
+ % filesystem doesn't support links).
+ major_device :: non_neg_integer(),
+ % Identifies the file system (Unix),
+ % or the drive number (A: = 0, B: = 1)
+ % (Windows).
+ %% The following are Unix specific.
+ %% They are set to zero on other operating systems.
+ minor_device :: non_neg_integer(), % Only valid for devices.
+ inode :: non_neg_integer(), % Inode number for file.
+ uid :: non_neg_integer(), % User id for owner.
+ gid :: non_neg_integer()}). % Group id for owner.
-record(file_descriptor,
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index 4d2e31a429..c66e823a04 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -515,6 +515,27 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
Drv,
Ls, Encoding)
end;
+%% ^R = backward search, ^S = forward search.
+%% Search is tricky to implement and does a lot of back-and-forth
+%% work with edlin.erl (from stdlib). Edlin takes care of writing
+%% and handling lines and escape characters to get out of search,
+%% whereas this module does the actual searching and appending to lines.
+%% Erlang's shell wasn't exactly meant to traverse the wall between
+%% line and line stack, so we at least restrict it by introducing
+%% new modes: search, search_quit, search_found. These are added to
+%% the regular ones (none, meta_left_sq_bracket) and handle special
+%% cases of history search.
+get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls, Encoding)
+ when ((Mode =:= none) and (Char =:= $\^R)) ->
+ send_drv_reqs(Drv, Rs),
+ %% drop current line, move to search mode. We store the current
+ %% prompt ('N>') and substitute it with the search prompt.
+ send_drv_reqs(Drv, edlin:erase_line(Cont)),
+ put(search_quit_prompt, edlin:prompt(Cont)),
+ Pbs = prompt_bytes("(search)`': ", Encoding),
+ {more_chars,Ncont,Nrs} = edlin:start(Pbs, search),
+ send_drv_reqs(Drv, Nrs),
+ get_line1(edlin:edit_line1(Cs, Ncont), Drv, Ls, Encoding);
get_line1({expand, Before, Cs0, Cont,Rs}, Drv, Ls0, Encoding) ->
send_drv_reqs(Drv, Rs),
ExpandFun = get(expand_fun),
@@ -535,8 +556,59 @@ get_line1({undefined,_Char,Cs,Cont,Rs}, Drv, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
send_drv(Drv, beep),
get_line1(edlin:edit_line(Cs, Cont), Drv, Ls, Encoding);
+%% The search item was found and accepted (new line entered on the exact
+%% result found)
+get_line1({_What,Cont={line,_Prompt,_Chars,search_found},Rs}, Drv, Ls0, Encoding) ->
+ Line = edlin:current_line(Cont),
+ %% this may create duplicate entries.
+ Ls = save_line(new_stack(get_lines(Ls0)), Line),
+ get_line1({done, Line, "", Rs}, Drv, Ls, Encoding);
+%% The search mode has been exited, but the user wants to remain in line
+%% editing mode wherever that was, but editing the search result.
+get_line1({What,Cont={line,_Prompt,_Chars,search_quit},Rs}, Drv, Ls, Encoding) ->
+ Line = edlin:current_chars(Cont),
+ %% Load back the old prompt with the correct line number.
+ case get(search_quit_prompt) of
+ undefined -> % should not happen. Fallback.
+ LsFallback = save_line(new_stack(get_lines(Ls)), Line),
+ get_line1({done, "\n", Line, Rs}, Drv, LsFallback, Encoding);
+ Prompt -> % redraw the line and keep going with the same stack position
+ NCont = {line,Prompt,{lists:reverse(Line),[]},none},
+ send_drv_reqs(Drv, Rs),
+ send_drv_reqs(Drv, edlin:erase_line(Cont)),
+ send_drv_reqs(Drv, edlin:redraw_line(NCont)),
+ get_line1({What, NCont ,[]}, Drv, pad_stack(Ls), Encoding)
+ end;
+%% Search mode is entered.
+get_line1({What,{line,Prompt,{RevCmd0,_Aft},search},Rs},
+ Drv, Ls0, Encoding) ->
+ send_drv_reqs(Drv, Rs),
+ %% Figure out search direction. ^S and ^R are returned through edlin
+ %% whenever we received a search while being already in search mode.
+ {Search, Ls1, RevCmd} = case RevCmd0 of
+ [$\^S|RevCmd1] ->
+ {fun search_down_stack/2, Ls0, RevCmd1};
+ [$\^R|RevCmd1] ->
+ {fun search_up_stack/2, Ls0, RevCmd1};
+ _ -> % new search, rewind stack for a proper search.
+ {fun search_up_stack/2, new_stack(get_lines(Ls0)), RevCmd0}
+ end,
+ Cmd = lists:reverse(RevCmd),
+ {Ls, NewStack} = case Search(Ls1, Cmd) of
+ {none, Ls2} ->
+ send_drv(Drv, beep),
+ {Ls2, {RevCmd, "': "}};
+ {Line, Ls2} -> % found. Complete the output edlin couldn't have done.
+ send_drv_reqs(Drv, [{put_chars, Encoding, Line}]),
+ {Ls2, {RevCmd, "': "++Line}}
+ end,
+ Cont = {line,Prompt,NewStack,search},
+ more_data(What, Cont, Drv, Ls, Encoding);
get_line1({What,Cont0,Rs}, Drv, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
+ more_data(What, Cont0, Drv, Ls, Encoding).
+
+more_data(What, Cont0, Drv, Ls, Encoding) ->
receive
{Drv,{data,Cs}} ->
get_line1(edlin:edit_line(Cs, Cont0), Drv, Ls, Encoding);
@@ -557,7 +629,6 @@ get_line1({What,Cont0,Rs}, Drv, Ls, Encoding) ->
get_line1(edlin:edit_line([], Cont0), Drv, Ls, Encoding)
end.
-
get_line_echo_off(Chars, Pbs, Drv) ->
send_drv_reqs(Drv, [{put_chars, unicode,Pbs}]),
get_line_echo_off1(edit_line(Chars,[]), Drv).
@@ -632,12 +703,46 @@ save_line({stack, U, {}, []}, Line) ->
save_line({stack, U, _L, D}, Line) ->
{stack, U, Line, D}.
-get_lines({stack, U, {}, []}) ->
+get_lines(Ls) -> get_all_lines(Ls).
+%get_lines({stack, U, {}, []}) ->
+% U;
+%get_lines({stack, U, {}, D}) ->
+% tl(lists:reverse(D, U));
+%get_lines({stack, U, L, D}) ->
+% get_lines({stack, U, {}, [L|D]}).
+
+%% There's a funny behaviour whenever the line stack doesn't have a "\n"
+%% at its end -- get_lines() seemed to work on the assumption it *will* be
+%% there, but the manipulations done with search history do not require it.
+%%
+%% It is an assumption because the function was built with either the full
+%% stack being on the 'Up' side (we're on the new line) where it isn't
+%% stripped. The only other case when it isn't on the 'Up' side is when
+%% someone has used the up/down arrows (or ^P and ^N) to navigate lines,
+%% in which case, a line with only a \n is stored at the end of the stack
+%% (the \n is returned by edlin:current_line/1).
+%%
+%% get_all_lines works the same as get_lines, but only strips the trailing
+%% character if it's a linebreak. Otherwise it's kept the same. This is
+%% because traversing the stack due to search history will *not* insert
+%% said empty line in the stack at the same time as other commands do,
+%% and thus it should not always be stripped unless we know a new line
+%% is the last entry.
+get_all_lines({stack, U, {}, []}) ->
U;
-get_lines({stack, U, {}, D}) ->
- tl(lists:reverse(D, U));
-get_lines({stack, U, L, D}) ->
- get_lines({stack, U, {}, [L|D]}).
+get_all_lines({stack, U, {}, D}) ->
+ case lists:reverse(D, U) of
+ ["\n"|Lines] -> Lines;
+ Lines -> Lines
+ end;
+get_all_lines({stack, U, L, D}) ->
+ get_all_lines({stack, U, {}, [L|D]}).
+
+%% For the same reason as above, though, we need to expand the stack
+%% in some cases to make sure we play nice with up/down arrows. We need
+%% to insert newlines, but not always.
+pad_stack({stack, U, L, D}) ->
+ {stack, U, L, D++["\n"]}.
save_line_buffer("\n", Lines) ->
save_line_buffer(Lines);
@@ -649,6 +754,27 @@ save_line_buffer(Line, Lines) ->
save_line_buffer(Lines) ->
put(line_buffer, Lines).
+search_up_stack(Stack, Substr) ->
+ case up_stack(Stack) of
+ {none,NewStack} -> {none,NewStack};
+ {L, NewStack} ->
+ case string:str(L, Substr) of
+ 0 -> search_up_stack(NewStack, Substr);
+ _ -> {string:strip(L,right,$\n), NewStack}
+ end
+ end.
+
+search_down_stack(Stack, Substr) ->
+ case down_stack(Stack) of
+ {none,NewStack} -> {none,NewStack};
+ {L, NewStack} ->
+ case string:str(L, Substr) of
+ 0 -> search_down_stack(NewStack, Substr);
+ _ -> {string:strip(L,right,$\n), NewStack}
+ end
+ end.
+
+
%% This is get_line without line editing (except for backspace) and
%% without echo.
get_password_line(Chars, Drv) ->
@@ -687,7 +813,7 @@ edit_password([$\177|Cs],[_|Chars]) ->%% is backspace enough?
edit_password([Char|Cs],Chars) ->
edit_password(Cs,[Char|Chars]).
-%% prompt_bytes(Prompt)
+%% prompt_bytes(Prompt, Encoding)
%% Return a flat list of characters for the Prompt.
prompt_bytes(Prompt, Encoding) ->
lists:flatten(io_lib:format_prompt(Prompt, Encoding)).
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 914f0d6127..f34341f561 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -60,7 +60,8 @@
-export([ read_not_really_compressed/1,
read_compressed_cooked/1, read_compressed_cooked_binary/1,
read_cooked_tar_problem/1,
- write_compressed/1, compress_errors/1, catenated_gzips/1]).
+ write_compressed/1, compress_errors/1, catenated_gzips/1,
+ compress_async_crash/1]).
-export([ make_link/1, read_link_info_for_non_link/1, symlinks/1]).
@@ -135,7 +136,8 @@ groups() ->
{compression, [],
[read_compressed_cooked, read_compressed_cooked_binary,
read_cooked_tar_problem, read_not_really_compressed,
- write_compressed, compress_errors, catenated_gzips]},
+ write_compressed, compress_errors, catenated_gzips,
+ compress_async_crash]},
{links, [],
[make_link, read_link_info_for_non_link, symlinks]}].
@@ -2312,6 +2314,57 @@ compress_errors(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+compress_async_crash(suite) -> [];
+compress_async_crash(doc) -> [];
+compress_async_crash(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line Path = filename:join(DataDir, "test.gz"),
+ ExpectedData = <<"qwerty">>,
+
+ ?line _ = ?FILE_MODULE:delete(Path),
+ ?line {ok, Fd} = ?FILE_MODULE:open(Path, [write, binary, compressed]),
+ ?line ok = ?FILE_MODULE:write(Fd, ExpectedData),
+ ?line ok = ?FILE_MODULE:close(Fd),
+
+ % Test that when using async thread pool, the emulator doesn't crash
+ % when the efile port driver is stopped while a compressed file operation
+ % is in progress (being carried by an async thread).
+ ?line ok = compress_async_crash_loop(10000, Path, ExpectedData),
+ ?line ok = ?FILE_MODULE:delete(Path),
+ ok.
+
+compress_async_crash_loop(0, _Path, _ExpectedData) ->
+ ok;
+compress_async_crash_loop(N, Path, ExpectedData) ->
+ Parent = self(),
+ {Pid, Ref} = spawn_monitor(
+ fun() ->
+ ?line {ok, Fd} = ?FILE_MODULE:open(
+ Path, [read, compressed, raw, binary]),
+ Len = byte_size(ExpectedData),
+ Parent ! {self(), continue},
+ ?line {ok, ExpectedData} = ?FILE_MODULE:read(Fd, Len),
+ ?line ok = ?FILE_MODULE:close(Fd),
+ receive foobar -> ok end
+ end),
+ receive
+ {Pid, continue} ->
+ exit(Pid, shutdown),
+ receive
+ {'DOWN', Ref, _, _, Reason} ->
+ ?line shutdown = Reason
+ end;
+ {'DOWN', Ref, _, _, Reason2} ->
+ test_server:fail({worker_exited, Reason2})
+ after 60000 ->
+ exit(Pid, shutdown),
+ erlang:demonitor(Ref, [flush]),
+ test_server:fail(worker_timeout)
+ end,
+ compress_async_crash_loop(N - 1, Path, ExpectedData).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
altname(doc) ->
"Test the file:altname/1 function";
altname(suite) ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 5d45b91ee5..a72e76f813 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -42,12 +42,13 @@
killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1,
several_accepts_in_one_go/1, accept_system_limit/1,
active_once_closed/1, send_timeout/1, send_timeout_active/1,
- otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
+ otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, wrapping_oct/1,
otp_9389/1]).
%% Internal exports.
-export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1,
- otp_7731_server/1, zombie_server/2]).
+ oct_acceptor/1,
+ otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]).
init_per_testcase(_Func, Config) when is_list(Config) ->
Dog = test_server:timetrap(test_server:seconds(240)),
@@ -75,6 +76,7 @@ all() ->
killing_acceptor, killing_multi_acceptors,
killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit,
active_once_closed, send_timeout, send_timeout_active, otp_7731,
+ wrapping_oct,
zombie_sockets, otp_7816, otp_8102, otp_9389].
groups() ->
@@ -589,7 +591,13 @@ iter_max_socks(doc) ->
"that we get the same number of sockets every time."];
iter_max_socks(Config) when is_list(Config) ->
N = 20,
- L = do_iter_max_socks(N, initalize),
+ %% Run on a different node in order to limit the effect if this test fails.
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok,Node} = test_server:start_node(test_iter_max_socks,slave,
+ [{args,"-pa " ++ Dir}]),
+ L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]),
+ test_server:stop_node(Node),
+
io:format("Result: ~p",[L]),
all_equal(L),
{comment, "Max sockets: " ++ integer_to_list(hd(L))}.
@@ -2575,3 +2583,71 @@ otp_9389_loop(S, OrigLinkHdr, State) ->
3000 ->
?line error({timeout,header})
end.
+
+wrapping_oct(doc) ->
+ "Check that 64bit octet counters work.";
+wrapping_oct(suite) ->
+ [];
+wrapping_oct(Config) when is_list(Config) ->
+ Dog = test_server:timetrap(test_server:seconds(600)),
+ {ok,Sock} = gen_tcp:listen(0,[{active,false},{mode,binary}]),
+ {ok,Port} = inet:port(Sock),
+ spawn_link(?MODULE,oct_acceptor,[Sock]),
+ Res = oct_datapump(Port,16#1FFFFFFFF),
+ gen_tcp:close(Sock),
+ test_server:timetrap_cancel(Dog),
+ ok = Res,
+ ok.
+
+oct_datapump(Port,N) ->
+ {ok,Sock} = gen_tcp:connect("localhost",Port,
+ [{active,false},{mode,binary}]),
+ oct_pump(Sock,N,binary:copy(<<$a:8>>,100000),0).
+
+oct_pump(S,N,_,_) when N =< 0 ->
+ gen_tcp:close(S),
+ ok;
+oct_pump(S,N,Bin,Last) ->
+ case gen_tcp:send(S,Bin) of
+ ok ->
+ {ok,Stat}=inet:getstat(S),
+ {_,R}=lists:keyfind(send_oct,1,Stat),
+ case (R < Last) of
+ true ->
+ io:format("ERROR (output) ~p < ~p~n",[R,Last]),
+ output_counter_error;
+ false ->
+ oct_pump(S,N-byte_size(Bin),Bin,R)
+ end;
+ _ ->
+ input_counter_error
+ end.
+
+
+oct_acceptor(Sock) ->
+ {ok,Data} = gen_tcp:accept(Sock),
+ oct_aloop(Data,0,0).
+
+oct_aloop(S,X,Times) ->
+ case gen_tcp:recv(S,0) of
+ {ok,_} ->
+ {ok,Stat}=inet:getstat(S),
+ {_,R}=lists:keyfind(recv_oct,1,Stat),
+ case (R < X) of
+ true ->
+ io:format("ERROR ~p < ~p~n",[R,X]),
+ gen_tcp:close(S),
+ input_counter_error;
+ false ->
+ case Times rem 16#FFFFF of
+ 0 ->
+ io:format("Read: ~p~n",[R]);
+ _ ->
+ ok
+ end,
+ oct_aloop(S,R,Times+1)
+ end;
+ _ ->
+ gen_tcp:close(S),
+ closed
+ end.
diff --git a/lib/megaco/doc/src/definitions/term.defs b/lib/megaco/doc/src/definitions/term.defs
index f3d6f865d2..57379eaa5d 100644
--- a/lib/megaco/doc/src/definitions/term.defs
+++ b/lib/megaco/doc/src/definitions/term.defs
@@ -110,7 +110,6 @@ the module Erlang in the application kernel","kenneth"},
{"Master Agent","Master Agent","The SNMP agent system consists of one Master Agent which terminates the SNMP protocol","mbj"}, {"MIB","Management Information Base (MIB)","An abstract definition of the management information available through a management interface in a system.","mbj"},
{"matching","matching","See pattern matching.","kenneth"},
{"message queue","message queue","The queue of not yet received messages that are in the mailbox of a process.","olin"},
-{"Mnemosyne","Mnemosyne","Mnemosyne was the query language of Mnesia up to the R11B release. Supersed by QLC.","hakan"},
{"Mnesia","Mnesia","Mnesia is a distributed Database Management System, appropriate for telecommunications applications and other applications with need of continuous operation and soft real-time properties.","hakan"},
{"MIBshort","MIB","See Management Information Base.","mbj"},
{"MIME","MIME","Multi-purpose Internet Mail Extensions.","jocke"},
diff --git a/lib/megaco/doc/src/definitions/term.defs.xml b/lib/megaco/doc/src/definitions/term.defs.xml
index 28ac0d6eaf..1c80ee8d80 100644
--- a/lib/megaco/doc/src/definitions/term.defs.xml
+++ b/lib/megaco/doc/src/definitions/term.defs.xml
@@ -794,13 +794,6 @@ The queue of not yet received messages that are in the mailbox of a process.
<resp>olin</resp>
</term>
<term>
- <id>Mnemosyne</id>
- <shortdef>Mnemosyne</shortdef>
- <def>
-Mnemosyne was the query language of Mnesia up to the R11B release. Supersed by QLC.</def>
- <resp>hakan</resp>
- </term>
- <term>
<id>Mnesia</id>
<shortdef>Mnesia</shortdef>
<def>
diff --git a/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
index b8146c345d..5faddb08c5 100644
--- a/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
+++ b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
@@ -76,6 +76,7 @@
typedef struct {
ErlDrvPort port;
+ ErlDrvTermData port_id;
char* digit_map_name_ptr;
int digit_map_name_len;
char* digit_map_value_ptr;
@@ -1497,6 +1498,7 @@ static ErlDrvData mfs_start(ErlDrvPort port, char *buf)
DBG( ("mfs_start -> entry\n") );
dataP->port = port;
+ dataP->port_id = driver_mk_port(port);
dataP->digit_map_name_ptr = NULL;
dataP->digit_map_name_len = 0;
dataP->digit_map_value_ptr = NULL;
@@ -1841,10 +1843,10 @@ static ErlDrvSSizeT mfs_control(ErlDrvData handle,
"\n term_spec_size: %d\n",
dataP->term_spec_index, dataP->term_spec_size) );
- driver_send_term(dataP->port,
- driver_caller(dataP->port),
- dataP->term_spec,
- dataP->term_spec_index);
+ erl_drv_send_term(dataP->port_id,
+ driver_caller(dataP->port),
+ dataP->term_spec,
+ dataP->term_spec_index);
if (dataP->text_buf != NULL) FREE(dataP->text_buf);
if (dataP->term_spec != NULL) FREE(dataP->term_spec);
diff --git a/lib/mnesia/include/mnemosyne.hrl b/lib/mnesia/include/mnemosyne.hrl
deleted file mode 100644
index eb6ec53ae1..0000000000
--- a/lib/mnesia/include/mnemosyne.hrl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--compile({parse_transform,mnemosyne}).
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 3d30debc53..3488d5c99b 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -2186,7 +2186,6 @@ system_info2(dump_log_time_threshold) -> mnesia_monitor:get_env(dump_log_time_th
system_info2(dump_log_update_in_place) ->
mnesia_monitor:get_env(dump_log_update_in_place);
system_info2(max_wait_for_decision) -> mnesia_monitor:get_env(max_wait_for_decision);
-system_info2(embedded_mnemosyne) -> mnesia_monitor:get_env(embedded_mnemosyne);
system_info2(ignore_fallback_at_startup) -> mnesia_monitor:get_env(ignore_fallback_at_startup);
system_info2(fallback_error_function) -> mnesia_monitor:get_env(fallback_error_function);
system_info2(log_version) -> mnesia_log:version();
@@ -2224,7 +2223,6 @@ system_info_items(yes) ->
dump_log_time_threshold,
dump_log_update_in_place,
dump_log_write_threshold,
- embedded_mnemosyne,
event_module,
extra_db_nodes,
fallback_activated,
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index c08bbc879f..d940bd1cb7 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -673,7 +673,6 @@ env() ->
dump_log_time_threshold,
dump_log_update_in_place,
dump_log_write_threshold,
- embedded_mnemosyne,
event_module,
extra_db_nodes,
ignore_fallback_at_startup,
@@ -706,8 +705,6 @@ default_env(dump_log_update_in_place) ->
true;
default_env(dump_log_write_threshold) ->
1000;
-default_env(embedded_mnemosyne) ->
- false;
default_env(event_module) ->
mnesia_event;
default_env(extra_db_nodes) ->
@@ -757,7 +754,6 @@ do_check_type(event_module, A) when is_atom(A) -> A;
do_check_type(ignore_fallback_at_startup, B) -> bool(B);
do_check_type(fallback_error_function, {Mod, Func})
when is_atom(Mod), is_atom(Func) -> {Mod, Func};
-do_check_type(embedded_mnemosyne, B) -> bool(B);
do_check_type(extra_db_nodes, L) when is_list(L) ->
Fun = fun(N) when N == node() -> false;
(A) when is_atom(A) -> true
diff --git a/lib/mnesia/src/mnesia_sup.erl b/lib/mnesia/src/mnesia_sup.erl
index 9ee4086f50..ef858d2364 100644
--- a/lib/mnesia/src/mnesia_sup.erl
+++ b/lib/mnesia/src/mnesia_sup.erl
@@ -60,9 +60,8 @@ init() ->
Event = event_procs(),
Kernel = kernel_procs(),
- Mnemosyne = mnemosyne_procs(),
- {ok, {Flags, Event ++ Kernel ++ Mnemosyne}}.
+ {ok, {Flags, Event ++ Kernel}}.
event_procs() ->
KillAfter = timer:seconds(30),
@@ -75,16 +74,6 @@ kernel_procs() ->
KA = infinity,
[{K, {K, start, []}, permanent, KA, supervisor, [K, supervisor]}].
-mnemosyne_procs() ->
- case mnesia_monitor:get_env(embedded_mnemosyne) of
- true ->
- Q = mnemosyne_sup,
- KA = infinity,
- [{Q, {Q, start, []}, permanent, KA, supervisor, [Q, supervisor]}];
- false ->
- []
- end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% event handler
diff --git a/lib/mnesia/test/mnesia.spec b/lib/mnesia/test/mnesia.spec
index 204d1519cb..653e515317 100644
--- a/lib/mnesia/test/mnesia.spec
+++ b/lib/mnesia/test/mnesia.spec
@@ -42,9 +42,6 @@
{skip_cases,"../mnesia_test",mnesia_measure_test,
[measure_all_api_functions],
"Not yet implemented"}.
-{skip_cases,"../mnesia_test",mnesia_measure_test,
- [mnemosyne_vs_mnesia_kernel],
- "Not yet implemented"}.
{skip_cases,"../mnesia_test",mnesia_examples_test,
[company],
"Not yet implemented"}.
diff --git a/lib/mnesia/test/mnesia_SUITE.erl b/lib/mnesia/test/mnesia_SUITE.erl
index 2267a94164..5dbb80d4eb 100644
--- a/lib/mnesia/test/mnesia_SUITE.erl
+++ b/lib/mnesia/test/mnesia_SUITE.erl
@@ -105,7 +105,6 @@ groups() ->
{otp_r4b, [],
[{mnesia_config_test, access_module},
{mnesia_config_test, dump_log_load_regulation},
- {mnesia_config_test, embedded_mnemosyne},
{mnesia_config_test, ignore_fallback_at_startup},
{mnesia_config_test, max_wait_for_decision},
{mnesia_consistency_test, consistency_after_restore},
diff --git a/lib/mnesia/test/mnesia_config_test.erl b/lib/mnesia/test/mnesia_config_test.erl
index 93510d539c..fd294780da 100644
--- a/lib/mnesia/test/mnesia_config_test.erl
+++ b/lib/mnesia/test/mnesia_config_test.erl
@@ -36,7 +36,6 @@
dump_log_load_regulation/1,
dump_log_update_in_place/1,
- embedded_mnemosyne/1,
event_module/1,
ignore_fallback_at_startup/1,
inconsistent_database/1,
@@ -104,7 +103,7 @@ end_per_testcase(Func, Conf) ->
all() ->
[access_module, auto_repair, backup_module, debug, dir,
dump_log_load_regulation, {group, dump_log_thresholds},
- dump_log_update_in_place, embedded_mnemosyne,
+ dump_log_update_in_place,
event_module, ignore_fallback_at_startup,
inconsistent_database, max_wait_for_decision,
send_compressed, app_test, {group, schema_config},
@@ -610,45 +609,6 @@ dump_log_load_regulation(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-embedded_mnemosyne(doc) ->
- ["Start Mnemosyne as an embedded part of Mnesia",
- "on some of the nodes"];
-embedded_mnemosyne(suite) ->
- [];
-embedded_mnemosyne(Config) when is_list(Config) ->
- Nodes = ?acquire_nodes(1, Config),
- Param = embedded_mnemosyne,
-
- %% Normal
- NoMnem = false,
- ?match(NoMnem, mnesia:system_info(Param)),
- ?match(undefined, whereis(mnemosyne_catalog)),
- ?match([], mnesia_test_lib:stop_mnesia(Nodes)),
-
- %% Bad
- Bad = arne_anka,
- ?match({error, {bad_type, Param, Bad}},
- mnesia:start([{Param, Bad}])),
-
- case code:priv_dir(mnemosyne) of
- {error, _} -> %% No mnemosyne on later systems
- ok;
- _ ->
- %% Mnemosyne as embedded application
- Mnem = true,
- ?match(undefined, whereis(mnemosyne_catalog)),
- ?match(ok,mnesia:start([{Param, Mnem}])),
- ?match(Mnem, mnesia:system_info(Param)),
- ?match(Pid when is_pid(Pid), whereis(mnemosyne_catalog)),
- ?match([], mnesia_test_lib:stop_mnesia(Nodes)),
- ?match(undefined, whereis(mnemosyne_catalog))
- end,
- ?verify_mnesia([], Nodes),
- ?cleanup(1, Config),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
ignore_fallback_at_startup(doc) ->
["Start Mnesia without rollback of the database to the fallback. ",
"Once Mnesia has been (re)started the installed fallback should",
diff --git a/lib/mnesia/test/mnesia_measure_test.erl b/lib/mnesia/test/mnesia_measure_test.erl
index e63689d83a..dfed302814 100644
--- a/lib/mnesia/test/mnesia_measure_test.erl
+++ b/lib/mnesia/test/mnesia_measure_test.erl
@@ -72,8 +72,7 @@ groups() ->
resource_consumption_at_full_load]},
{benchmarks, [],
[{group, meter}, cost, dbn_meters,
- measure_all_api_functions, {group, tpcb},
- mnemosyne_vs_mnesia_kernel]},
+ measure_all_api_functions, {group, tpcb}]},
{tpcb, [], [ram_tpcb, disc_tpcb, disc_only_tpcb]},
{meter, [], [ram_meter, disc_meter, disc_only_meter]}].
diff --git a/lib/orber/src/orber_ifr_exceptiondef.erl b/lib/orber/src/orber_ifr_exceptiondef.erl
index 7665d3d1bc..94c25cc4a5 100644
--- a/lib/orber/src/orber_ifr_exceptiondef.erl
+++ b/lib/orber/src/orber_ifr_exceptiondef.erl
@@ -111,26 +111,6 @@ cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
describe({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
orber_ifr_contained:describe({ObjType,ObjID}).
-%%% *** This function should be removed. Use
-%%% orber_ifr_repository:lookup_id/2 instead.
-
-%%lookup_id(SearchId) ->
-%% _F = fun() ->
-%% Q = query [X.ir_Internal_ID || X <- table(ir_ExceptionDef)]
-%% end,
-%% mnemosyne:eval(Q)
-%% end,
-%% case orber_ifr_utils:ifr_transaction_read(_F) of
-%% ?read_check_2() ->
-%% {ok, []};
-%% ?read_check_1(Rep_IDs) ->
-%% ExceptionDefs = lists:map(fun(X) -> {ir_ExceptionDef, X} end,
-%% Rep_IDs),
-%% {ok, lists:filter(fun(X) -> orber_ifr_exceptiondef:'_get_id'(X) ==
-%% SearchId end,
-%% ExceptionDefs)}
-%% end.
-
move({ObjType, ObjID}, New_container, New_name, New_version)
?tcheck(ir_ExceptionDef, ObjType) ->
orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 4a0f70ba71..9d591c0d05 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -649,7 +649,6 @@ reserved_word('fun') -> true;
reserved_word('if') -> true;
reserved_word('let') -> true;
reserved_word('of') -> true;
-reserved_word('query') -> true;
reserved_word('receive') -> true;
reserved_word('when') -> true;
reserved_word('bnot') -> true;
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 5686920dd4..9b7d98728f 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -509,7 +509,7 @@ pkix_normalize_name(Issuer) ->
%%--------------------------------------------------------------------
-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
CertChain :: [binary()] ,
- Options :: proplist:proplist()) ->
+ Options :: proplists:proplist()) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
@@ -547,7 +547,7 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
%--------------------------------------------------------------------
-spec pkix_crls_validate(#'OTPCertificate'{},
[{DP::#'DistributionPoint'{} ,CRL::#'CertificateList'{}}],
- Options :: proplist:proplist()) -> valid | {bad_cert, revocation_status_undetermined}
+ Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined}
| {bad_cert, {revoked, crl_reason()}}.
%% Description: Performs a basic path validation according to RFC 5280.
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index b8af89d040..bd20a5546b 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.17
+PUBLIC_KEY_VSN = 0.18
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index b6b8751f6c..5b94dcb051 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2012</year>
+ <year>1996</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,86 @@
<section>
+ <title>SNMP Development Toolkit 4.23</title>
+<!--
+ <p>Version 4.23 supports code replacement in runtime from/to
+ version 4.22.1,
+ 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
+-->
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[manager] Polish return values of snmpm_user_default according
+ to snmpm_user doc.</p>
+ <p>Luca Favatella</p>
+ <p>Own Id: OTP-10671</p>
+ </item>
+
+ <item>
+ <p>[agent] Remove runtime warning in snmpa_agent because of
+ tuple fun usage. </p>
+ <p>Luca Favatella</p>
+ <p>Own Id: OTP-10672</p>
+ </item>
+
+ <item>
+ <p>[manager] SNMP manager performance optimization. </p>
+ <p>Ivan Dubovik</p>
+ <p>Own Id: OTP-10673</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
+ <p>Own Id: OTP-9884</p>
+ <p>Aux Id: Seq 11995</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[manager] The old Addr-and-Port based API functions, previously
+ long deprecated and marked for deletion in R16B, has now been
+ removed. </p>
+ <p>Own Id: OTP-10027</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 4.23 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.22.1</title>
<p>Version 4.22.1 supports code replacement in runtime from/to
version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and
@@ -126,70 +206,6 @@
<section>
- <title>SNMP Development Toolkit 4.23</title>
- <p>Version 4.23 supports code replacement in runtime from/to
- version 4.22,
- 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
-
-<!--
- <list type="bulleted">
- <item>
- <p>[agent] Documenting previously existing but undocumented function,
- <seealso marker="snmp_generic#get_table_info">snmp_generic:get_table_info/2</seealso>. </p>
- <p>Own Id: OTP-9942</p>
- </item>
-
- </list>
--->
-
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] Simultaneous
- <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
- calls can interfere.
- The master agent did not check if a backup was already in
- progress when a backup request was accepted. </p>
- <p>Own Id: OTP-9884</p>
- <p>Aux Id: Seq 11995</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
-<!--
- <p>-</p>
--->
-
- <list type="bulleted">
- <item>
- <p>[manager] The old Addr-and-Port based API functions, previously
- long deprecated and marked for deletion in R16B, has now been
- removed. </p>
- <p>Own Id: OTP-10027</p>
- </item>
-
- </list>
- </section>
-
- </section> <!-- 4.23 -->
-
-
- <section>
<title>SNMP Development Toolkit 4.22</title>
<p>Version 4.22 supports code replacement in runtime from/to
version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index 9d30e332f1..57846db13b 100644
--- a/lib/snmp/src/agent/snmpa_agent.erl
+++ b/lib/snmp/src/agent/snmpa_agent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1134,7 +1134,7 @@ handle_call({get, Vars, Context}, _From, S) ->
"~n Vars: ~p"
"~n Context: ~p", [Vars, Context]),
put_pdu_data({undefined, undefined, undefined, undefined, Context}),
- case catch mapfoldl({?MODULE, tr_var}, [], 1, Vars) of
+ case catch mapfoldl(fun ?MODULE:tr_var/2, [], 1, Vars) of
{error, Reason} -> {reply, {error, Reason}, S};
{_, Varbinds} ->
?vdebug("Varbinds: ~p",[Varbinds]),
@@ -1155,7 +1155,7 @@ handle_call({get_next, Vars, Context}, _From, S) ->
"~n Vars: ~p"
"~n Context: ~p",[Vars, Context]),
put_pdu_data({undefined, undefined, undefined, undefined, Context}),
- case catch mapfoldl({?MODULE, tr_var}, [], 1, Vars) of
+ case catch mapfoldl(fun ?MODULE:tr_var/2, [], 1, Vars) of
{error, Reason} -> {reply, {error, Reason}, S};
{_, Varbinds} ->
?vdebug("Varbinds: ~p",[Varbinds]),
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 593ddd82bd..a6abf8439a 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,582 +22,12 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.22",
- [
- {load_module, snmpm, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
- ]
- },
- {"4.21.7",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.6",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.5",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.4",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.3",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.2",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21.1",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- },
- {"4.21",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
-
- {add_module, snmpm_net_if_mt}
- ]
- }
],
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.22",
- [
- {load_module, snmpm, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
- ]
- },
- {"4.21.7",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.6",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.5",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.4",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.3",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.2",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21.1",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- },
- {"4.21",
- [
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
-
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
-
- {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_verbosity, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf, snmpa_mib_lib]},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
-
- {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
- ]
- }
]
+
}.
diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl
index 484954addb..61d22362cc 100644
--- a/lib/snmp/src/manager/snmpm_server.erl
+++ b/lib/snmp/src/manager/snmpm_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3163,17 +3163,16 @@ request_id() ->
%%----------------------------------------------------------------------
agent_data(TargetName, SendOpts) ->
- case snmpm_config:agent_info(TargetName, all) of
- {ok, Info} ->
- Version = agent_data_item(version, Info),
+ case snmpm_config:agent_info(TargetName, version) of
+ {ok, Version} ->
MsgData =
case Version of
v3 ->
- DefSecModel = agent_data_item(sec_model, Info),
- DefSecName = agent_data_item(sec_name, Info),
- DefSecLevel = agent_data_item(sec_level, Info),
+ DefSecModel = agent_data_item(sec_model, TargetName),
+ DefSecName = agent_data_item(sec_name, TargetName),
+ DefSecLevel = agent_data_item(sec_level, TargetName),
- EngineId = agent_data_item(engine_id, Info),
+ EngineId = agent_data_item(engine_id, TargetName),
CtxName = agent_data_item(context,
SendOpts,
?DEFAULT_CONTEXT),
@@ -3191,8 +3190,8 @@ agent_data(TargetName, SendOpts) ->
{SecModel, SecName, mk_sec_level_flag(SecLevel),
EngineId, CtxName, TargetName};
_ ->
- DefComm = agent_data_item(community, Info),
- DefSecModel = agent_data_item(sec_model, Info),
+ DefComm = agent_data_item(community, TargetName),
+ DefSecModel = agent_data_item(sec_model, TargetName),
Comm = agent_data_item(community,
SendOpts,
@@ -3203,21 +3202,21 @@ agent_data(TargetName, SendOpts) ->
{Comm, SecModel}
end,
- Domain = agent_data_item(tdomain, Info),
- Addr = agent_data_item(address, Info),
- Port = agent_data_item(port, Info),
- RegType = agent_data_item(reg_type, Info),
+ Domain = agent_data_item(tdomain, TargetName),
+ Addr = agent_data_item(address, TargetName),
+ Port = agent_data_item(port, TargetName),
+ RegType = agent_data_item(reg_type, TargetName),
{ok, RegType, Domain, Addr, Port, version(Version), MsgData};
Error ->
Error
end.
-agent_data_item(Item, Info) ->
- case lists:keysearch(Item, 1, Info) of
- {value, {_, Val}} ->
+agent_data_item(Item, TargetName) ->
+ case snmpm_config:agent_info(TargetName, Item) of
+ {ok, Val} ->
Val;
- false ->
- throw({error, {not_found, Item, Info}})
+ {error, not_found} ->
+ throw({error, {not_found, Item, TargetName}})
end.
agent_data_item(Item, Info, Default) ->
diff --git a/lib/snmp/src/manager/snmpm_user_default.erl b/lib/snmp/src/manager/snmpm_user_default.erl
index d90fc3f258..015198cb76 100644
--- a/lib/snmp/src/manager/snmpm_user_default.erl
+++ b/lib/snmp/src/manager/snmpm_user_default.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,7 +62,7 @@ handle_trap(TargetName, SnmpTrap, UserData) ->
"~n SnmpTrap: ~p"
"~n UserData: ~p",
[TargetName, SnmpTrap, UserData]),
- ok.
+ ignore.
handle_inform(TargetName, SnmpInform, UserData) ->
@@ -80,7 +80,7 @@ handle_report(TargetName, SnmpReport, UserData) ->
"~n SnmpReport: ~p"
"~n UserData: ~p",
[TargetName, SnmpReport, UserData]),
- ok.
+ ignore.
info(F, A) ->
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 826a11f1f4..cbd8166bb9 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,12 +19,14 @@
{"%VSN%",
[
+ {<<"2.1.2">>, [{restart_application, ssh}]},
{<<"2.1.1">>, [{restart_application, ssh}]},
{<<"2.1">>, [{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
{<<"1\\.*">>, [{restart_application, ssh}]}
],
[
+ {<<"2.1.2">>, [{restart_application, ssh}]},
{<<"2.1.1">>, [{restart_application, ssh}]},
{<<"2.1">>,[{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 3ef26b1678..193f877b98 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -31,11 +31,6 @@
stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
shell/1, shell/2, shell/3]).
--deprecated({sign_data, 2, next_major_release}).
--deprecated({verify_data, 3, next_major_release}).
-
--export([sign_data/2, verify_data/3]).
-
%%--------------------------------------------------------------------
%% Function: start([, Type]) -> ok
%%
@@ -278,7 +273,9 @@ do_start_daemon(Host, Port, Options, SocketOptions) ->
{ok, SysSup} ->
{ok, SysSup};
{error, {already_started, _}} ->
- {error, eaddrinuse}
+ {error, eaddrinuse};
+ {error, R} ->
+ {error, R}
catch
exit:{noproc, _} ->
{error, ssh_not_started}
@@ -392,8 +389,8 @@ handle_ssh_option({public_key_alg, Value} = Opt) when Value == 'ssh-rsa'; Value
Opt;
handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), length(Value) >= 1 ->
case handle_pref_algs(Value, []) of
- true ->
- Opt;
+ {true, NewOpts} ->
+ NewOpts;
_ ->
throw({error, {eoptions, Opt}})
end;
@@ -501,38 +498,3 @@ inetopt(false) ->
%%%
%% Deprecated
%%%
-
-%%--------------------------------------------------------------------
-%% Function: sign_data(Data, Algorithm) -> binary() |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH key to sign data.
-%%--------------------------------------------------------------------
-sign_data(Data, Algorithm) when is_binary(Data) ->
- case ssh_file:user_key(Algorithm,[]) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- public_key:sign(Data, sha, Key);
- Error ->
- Error
- end.
-
-%%--------------------------------------------------------------------
-%% Function: verify_data(Data, Signature, Algorithm) -> ok |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Signature = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH signature to verify data.
-%%--------------------------------------------------------------------
-verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
- case ssh_file:user_key(Algorithm, []) of
- {ok, #'RSAPrivateKey'{publicExponent = E, modulus = N}} when Algorithm == "ssh-rsa" ->
- public_key:verify(Data, sha, Signature, #'RSAPublicKey'{publicExponent = E, modulus = N});
- Error ->
- Error
- end.
diff --git a/lib/ssh/src/ssh_client_key_api.erl b/lib/ssh/src/ssh_client_key_api.erl
index eed0b85f47..58054a9fc5 100644
--- a/lib/ssh/src/ssh_client_key_api.erl
+++ b/lib/ssh/src/ssh_client_key_api.erl
@@ -26,7 +26,7 @@
Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplist()) ->
boolean().
--callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplists()) ->
+-callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplist()) ->
{ok, PrivateKey :: #'RSAPrivateKey'{}| #'DSAPrivateKey'{} | term()} | {error, string()}.
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 88b45111ff..9378686242 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -422,11 +422,15 @@ userauth(#ssh_msg_userauth_failure{authentications = Methodes},
#state{ssh_params = #ssh{role = client,
userauth_methods = none} = Ssh0} = State) ->
AuthMethods = string:tokens(Methodes, ","),
- {Msg, Ssh} = ssh_auth:userauth_request_msg(
- Ssh0#ssh{userauth_methods = AuthMethods}),
- send_msg(Msg, State),
- {next_state, userauth, next_packet(State#state{ssh_params = Ssh})};
-
+ Ssh1 = Ssh0#ssh{userauth_methods = AuthMethods},
+ case ssh_auth:userauth_request_msg(Ssh1) of
+ {disconnect, DisconnectMsg, {Msg, Ssh}} ->
+ send_msg(Msg, State),
+ handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh});
+ {Msg, Ssh} ->
+ send_msg(Msg, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ end;
%% The prefered authentication method failed try next method
userauth(#ssh_msg_userauth_failure{},
#state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 921ec2206a..71666a3179 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.1.2
+SSH_VSN = 2.1.3
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 49bbd5d27d..73cda03b2f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2012</year>
+ <year>1999</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,10 +22,6 @@
</legalnotice>
<title>SSL Release Notes</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <docno></docno>
- <date>2003-08-03</date>
- <rev>G</rev>
<file>notes.xml</file>
</header>
<p>This document describes the changes made to the SSL application.</p>
@@ -605,1285 +601,7 @@
</item>
</list>
</section>
-
- </section>
-
-
- <section><title>SSL 3.11.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fixed handling of several ssl/tls packets arriving at the
- same time. This was broken during a refactoring of the
- code.</p>
- <p>
- Own Id: OTP-8679</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Added missing checks for padding and Mac value. Removed
- code for export ciphers and DH certificates as we decided
- not to support them.</p>
- <p>
- Own Id: OTP-7047</p>
- </item>
- <item>
- <p>
- New ssl will no longer return esslerrssl to be backwards
- compatible with old ssl as this hids infomation from the
- user. format_error/1 has been updated to support new ssl.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-7049</p>
- </item>
- <item>
- <p>
- New ssl now supports secure renegotiation as described by
- RFC 5746.</p>
- <p>
- Own Id: OTP-8568</p>
- </item>
- <item>
- <p>
- Alert handling has been improved to better handle
- unexpected but valid messages and the implementation is
- also changed to avoid timing related issues that could
- cause different error messages depending on network
- latency. Packet handling was sort of broken but would
- mostly work as expected when socket was in binary mode.
- This has now been fixed.</p>
- <p>
- Own Id: OTP-8588</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.11</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fixes handling of the option fail_if_no_peer_cert and
- some undocumented options. Thanks to Rory Byrne.</p>
- <p>
- Own Id: OTP-8557</p>
- </item>
- </list>
- </section>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Support for Diffie-Hellman. ssl-3.11 requires
- public_key-0.6.</p>
- <p>
- Own Id: OTP-7046</p>
- </item>
- <item>
- <p>
- New ssl now properly handles ssl renegotiation, and
- initiates a renegotiation if ssl/ltls-sequence numbers
- comes close to the max value. However RFC-5746 is not yet
- supported, but will be in an upcoming release.</p>
- <p>
- Own Id: OTP-8517</p>
- </item>
- <item>
- <p>
- When gen_tcp is configured with the {packet,http} option,
- it automatically switches to expect HTTP Headers after a
- HTTP Request/Response line has been received. This update
- fixes ssl to behave in the same way. Thanks to Rory
- Byrne.</p>
- <p>
- Own Id: OTP-8545</p>
- </item>
- <item>
- <p>
- Ssl now correctly verifies the extended_key_usage
- extension and also allows the user to verify application
- specific extensions by supplying an appropriate fun.</p>
- <p>
- Own Id: OTP-8554 Aux Id: OTP-8553 </p>
- </item>
- <item>
- <p>
- Fixed ssl:transport_accept/2 to return properly when
- socket is closed. Thanks to Rory Byrne.</p>
- <p>
- Own Id: OTP-8560</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fixed a crash in the certificate certification part.</p>
- <p>
- Own Id: OTP-8510 Aux Id: seq11525 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p><c>ssl:send/2</c> ignored packet option, fix provided
- by YAMASHINA Hio.</p>
- <p>Fixed a file cache bug which caused problems when the
- same file was used for both cert and cacert.</p>
- <p>Allow <c>ssl:listen/2</c> to be called with option
- {ssl_imp, old}.</p>
- <p> Fixed ssl:setopts(Socket, binary) which didn't work
- for 'new' ssl.</p>.
- <p>
- Own Id: OTP-8441</p>
- </item>
- <item>
- <p>
- Do a controlled shutdown if a non ssl packet arrives as
- the first packet.</p>
- <p>
- Own Id: OTP-8459 Aux Id: seq11505 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Fixed session reuse (in new_ssl), thanks Wil Tan.</p>
- <p>Send CA list during Certificate Request (in new_ssl) ,
- thanks Wil Tan.</p> <p><c>NOTE</c>: SSL (new_ssl)
- requires public_key-0.5.</p>
- <p>
- Own Id: OTP-8372</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.7</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- A ticker process could potentially be blocked
- indefinitely trying to send a tick to a node not
- responding. If this happened, the connection would not be
- brought down as it should.</p>
- <p> This requires erts-5.7.4 and kernel-2.13.4 or later
- to be able to get the erlang distribution over ssl to work.</p>
- <p>
- Own Id: OTP-8218</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The documentation is now built with open source tools
- (xsltproc and fop) that exists on most platforms. One
- visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8250</p>
- </item>
- <item>
- <p>
- Code cleanup from Kostis.</p>
- <p>
- Own Id: OTP-8260</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.6</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The ssl:ssl_accept/3 issue was not properly fixed in the
- previous patch, see OTP-8244.</p>
- <p>
- Own Id: OTP-8275 Aux Id: seq11451 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.5</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Allow clients to not send certificates if option
- <c>fail_if_no_peer_cert</c> was not set.</p>
- <p>
- Own Id: OTP-8224</p>
- </item>
- <item>
- <p>An ssl:ssl_accept/3 could crash a connection if the
- timing was wrong.</p> <p>Removed info message if the
- socket closed without a proper disconnect from the ssl
- layer. </p> <p>ssl:send/2 is now blocking until the
- message is sent.</p>
- <p>
- Own Id: OTP-8244 Aux Id: seq11420 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- A client could avoid a certificate check if the client
- code didn't send the requested certificate.</p>
- <p>
- Own Id: OTP-8137</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 3.10.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Packet handling was not implemented correctly.</p>
- <p>Inet option handling support have been improved.</p>
- <p>The <c>verify_fun</c> is now invoked even if
- verify_peer is used, that implies that by default
- {bad_cert,unknown_ca} is an accepted fault during the
- client connection phase. The check can still be done by
- suppling another verify_fun.</p>
- <p>
- Own Id: OTP-8011 Aux Id: seq11287 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-
-<section><title>SSL 3.10.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- A "new_ssl" socket was not closed if the controlling
- process died without calling ssl:close/1.</p>
- <p>
- Own Id: OTP-7963 Aux Id: seq11276 </p>
- </item>
- </list>
</section>
-
-</section>
-
-<section><title>SSL 3.10.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fixed bug that caused the ssl handshake finished message
- to be calculated wrongly under the circumstances that the
- server did not send the trusted cert and that the
- previous cert did not have the extension telling us the
- trusted certs name. This manifested it self as
- bad_record_mac alert from the server.</p>
- <p>
- Own Id: OTP-7878</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The cacertsfile option is now optional for ssl servers.</p>
- <p>
- Own Id: OTP-7656</p>
- </item>
- <item>
- <p>
- For the ssl client the options cacertfile, certfile and
- keyfile are now optional as they are not always needed
- depending on configuration of the client itself and the
- configuration of the server. Also as PEM-files may
- contain more than one entry the keyfile option will
- default to the same file as given by the certfile option.</p>
- <p>
- Own Id: OTP-7870</p>
- </item>
- <item>
- <p>
- Added new ssl client option verify_fun.</p>
- <p>
- Own Id: OTP-7871</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>SSL 3.10</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Error log entries are now formatted correctly.</p>
- <p>
- Own Id: OTP-7258</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- All handling of X509-certificates and public keys have
- been moved to the new application public_key.</p>
- <p>
- Own Id: OTP-6894</p>
- </item>
- <item>
- <p>
- New ssl now supports SSL-3.0 and TLS-1.0</p>
- <p>
- Own Id: OTP-7037</p>
- </item>
- <item>
- <p>
- New ssl now supports all inet-packet types.</p>
- <p>
- Own Id: OTP-7039</p>
- </item>
- <item>
- <p>
- The new ssl-server is now able to send a certificate
- request to the client. However new options may be
- introduced later to fully support all features regarding
- certificate requests.</p>
- <p>
- Own Id: OTP-7150</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Known Bugs and Problems</title>
- <list>
- <item>
- <p>
- Running erlang distribution over ssl don't work as
- described in the documentation.</p>
- <p>
- Own Id: OTP-7536</p>
- </item>
- </list>
- </section>
-
- </section>
-
-
- <section><title>SSL 3.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- ssl_prim.erl was passing an FD rather than an #sslsocket
- to ssl_broker:ssl_accept_prim. This could cause problems
- in the deprecated accept function, this will not cause
- any more problems however this function is deprecated!</p>
- <p>
- Own Id: OTP-6926</p>
- </item>
- <item>
- <p>
- Erlang distribution over ssl was broken after R11B-0,
- this has now been fixed.</p>
- <p>
- Own Id: OTP-7004</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- All inet options are available in the new ssl
- implementation that is released as a alfa in ssl-3.9 and
- will replace the old implementation in ssl-4.0. This will
- not be fixed in the old implementation.</p>
- <p>
- Own Id: OTP-4677</p>
- </item>
- <item>
- <p>
- The new ssl implementation released as a alfa in this
- version supports upgrading of a tcp connection to an ssl
- connection so that http client and servers may implement
- RFC 2817.</p>
- <p>
- Own Id: OTP-5510</p>
- </item>
- <item>
- <p>A new implementation of ssl is released as a alfa
- version in ssl-3.9 it will later replace the old
- implementation in ssl-4.0. The new implementation can be
- accessed by providing the option {ssl_imp, new} to the
- ssl:connect and ssl:listen functions.</p>
- <p>The new implementation is Erlang based and all logic
- is in Erlang and only payload encryption calculations are
- done in C via the crypto application. The main reason for
- making a new implementation is that the old solution was
- very crippled as the control of the ssl-socket was deep
- down in openssl making it hard if not impossible to
- support all inet options, ipv6 and upgrade of a tcp
- connection to an ssl connection. The alfa version has a
- few limitations that will be removed before the ssl-4.0
- release. Main differences and limitations in the alfa are
- listed below.</p>
-
- <list type="bulleted"> <item>New ssl requires the crypto
- application.</item> <item>The option reuseaddr is
- supported and the default value is false as in gen_tcp.
- Old ssl is patched to accept that the option is set to
- true to provide a smoother migration between the
- versions. In old ssl the option is hard coded to
- true.</item> <item>ssl:version/0 is replaced by
- ssl:versions/0</item> <item>ssl:ciphers/0 is replaced by
- ssl:cipher_suites/0</item> <item>ssl:pid/1 is a
- meaningless function in new ssl and will be deprecated in
- ssl-4.0 until it is removed it will return a valid but
- meaningless pid.</item> <item>New API functions are
- ssl:shutdown/2, ssl:cipher_suites/[0,1] and
- ssl:versions/0</item> <item>Diffie-Hellman keyexchange is
- not supported.</item> <item>Not all inet packet types are
- supported.</item> <item>CRL and policy certificate
- extensions are not supported.</item> <item>In this alfa
- only sslv3 is enabled, although tlsv1 and tlsv1.1
- versions are implemented and will be supported in future
- versions.</item> <item>For security reasons sslv2 is not
- supported.</item> </list>
- <p>
- Own Id: OTP-6619</p>
- </item>
- <item>
- <p>
- New ssl implementation, released as alfa in ssl-3.9,
- supports ipv6. It will not be supported in the old
- implementation.</p>
- <p>
- Own Id: OTP-6637 Aux Id: OTP-6636 </p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section>
- <title>SSL 3.1.1.1</title>
-
- <section>
- <title>Minor Makefile changes</title>
- <list type="bulleted">
- <item>
- <p>Removed use of <c>erl_flags</c> from Makefile.</p>
- <p>Own Id: OTP-6689</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.1.1</title>
-
- <section>
- <title>Crash on error in ssl_accept</title>
- <list type="bulleted">
- <item>
- <p>A bug in ssl_accept could cause all ssl
- connections to hang when a connection
- attempt was closed by the client while
- the server was in <c>ssl_accept</c>.</p>
- <p>Own Id: OTP-6612 Aux Id: seq10599</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>SSL now uses a two-phase accept, with a separate accept
- calls for the socket and the ssl protocol. This avoids
- timeouts when a client doesn't initiate ssl handshake.</p>
- <p>With the old implementation of accept, the server
- was locked by a client, if the client didn't do
- proper ssl handshake.</p>
- <p>Own Id: OTP-6418 Aux Id: seq10105</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.12</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>An integer array pointing to a struct pollfd array, is
- now reset before file descriptors are collected to be
- included in a call to poll(). This is to prevent file
- descriptors to be mixed up.</p>
- <p>Own Id: OTP-6084</p>
- </item>
- <item>
- <p>The generation of the module ssl_pkix_oid contained
- multiple identifiers, which made the mapping between
- atoms and identifiers not one-to-one.</p>
- <p>Own Id: OTP-6085</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.11</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The state of a connection in active mode could be in a
- restrictive state, so that an internal tcp_closed message
- was incorrectly considered illegal, resulting in a
- premature termination of the connection process.</p>
- <p>Own Id: OTP-5972 Aux Id: seq10188 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.10</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Erlang distribution over SSL was broken. Corrected.
- (Thanks to Fredrik Thulin.)</p>
- <p>Own Id: OTP-5863</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.9</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The port program for the ssl application could waste huge
- amounts of CPU time if a write could not be completed
- directly and was put in the write queue. (Only on platforms
- where poll() is used, such as Solaris and Linux.)</p>
- <p>Own Id: OTP-5784</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.8</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>A process reading only a portion of a sufficiently large
- amount of data from an accepted socket, and then quering
- the ssl library (e.g. ssl:getpeername()), would cause a
- global deadlock in the esock port program.</p>
- <p>Own Id: OTP-5702</p>
- </item>
- <item>
- <p>A spelling error in the module <c>ssl_pkix</c> caused the
- call to <c>ssl:peercert/2</c> to fail when the option
- <c>subject</c> was used.</p>
- <p>Own Id: OTP-5708</p>
- </item>
- <item>
- <p>Because fopen() on Solaris 8 can't handle file
- descriptor numbers above 255, reading of certificate
- files would fail if all file descriptors below 256 were
- in use (typically, if many connections were open). This
- problem has been worked around.</p>
- <p>The ssl application's port program used to use
- select(), which meant that it could not handle more than
- FD_SETSIZE file descriptors (usually 1024). To eliminate
- that limitation, poll() is now used on all platforms that
- support it.</p>
- <p>Solaris/Sparc, 64-bit emulator: The SO_REUSEADDR
- option was not set for listen sockets, which essentially
- made the ssl application unusable. Corrected.</p>
- <p>The default listen queue size for ssl port program was
- changed to 128 (from 5).</p>
- <p>Own Id: OTP-5755 Aux Id: seq10068 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Ssl 3.0.7</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The R/W buffer length i esock.c was too small. It has
- been increased from 4k to 32k.</p>
- <p>Own Id: OTP-5620</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Ssl 3.0.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>A configuration option for choosing protocol versions has
- been added (<c>sslv2</c>, <c>sslv3</c>, and
- <c>tlsv1</c>).</p>
- <p>Own Id: OTP-5429 Aux Id: seq9755 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Ssl 3.0.5</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Linked in drivers in the crypto, and asn1 applications
- are now compiled with the -D_THREAD_SAFE and -D_REENTRANT
- switches on unix when the emulator has thread support
- enabled.</p>
- <p>Linked in drivers on MacOSX are not compiled with the
- undocumented -lbundle1.o switch anymore. Thanks to Sean
- Hinde who sent us a patch.</p>
- <p>Linked in driver in crypto, and port programs in ssl, now
- compiles on OSF1.</p>
- <p>Minor makefile improvements in runtime_tools.</p>
- <p>Own Id: OTP-5346</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Ssl 3.0.4</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p><c>ssl:recv/3</c> with finite timeout value, closed the
- connection at timeout.</p>
- <p>Own Id: OTP-4882</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Ssl 3.0.3</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>When a file descriptor was marked for closing, and
- end-of-file condition had already been detected, the file
- descriptor was never closed.</p>
- <p>Own Id: OTP-5093 Aux Id: seq8806 </p>
- </item>
- <item>
- <p>When the number of open file descriptors reached
- FD_SETSIZE, the SSL port program entered a busy loop.</p>
- <p>Own Id: OTP-5094 Aux Id: seq8806 </p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The SSL application now supports SSL sessions for
- servers, which typically speeds up HTTP requests from
- browsers.</p>
- <p>Own Id: OTP-5095</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.2</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The UTF8String type is now defined in asn1-1.4.4.2 and
- later. Therefore the definitions of UTF8String has been
- removed from the ASN.1 modules PKIX1Explicit88.asn1 and
- PKIXAttributeCertificate.asn1. The SSL application can now
- only be built using asn-1.4.4.2 or later.</p>
- <p>OwnId: OTP-4971.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <p>See SSL-3.0.
- </p>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>An unexpected object identifier would crash <c>ssl:peercert</c>. </p>
- <p>OwnId: OTP-4771.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <p>See SSL-3.0.
- </p>
- </section>
- </section>
-
- <section>
- <title>SSL 3.0</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The <c>cache_timout</c> option was silently ignored. It had
- to do with SSL sessions, where multiple connections can occur.
- Since the Erlang SSL application does not support sessions the
- option is still ignored, and consequently the documentation
- about it has been removed.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>The Erlang SSL application is now based on OpenSSL version
- 0.9.7a. OpenSSL 0.9.6 should also work.</p>
- <p>OwnId: OTP-4002</p>
- </item>
- <item>
- <p>When connecting it is now possible to bind to a local address
- and local port. </p>
- <p>OwnId: OTP-4675</p>
- </item>
- <item>
- <p>The <c>ssl_esock</c> port program is now part of the
- distribution and thus does not have to be created
- explicitly. It is dynamically linked to OpenSSL
- libraries in a "standard" location (typically
- <c>/usr/local/lib</c> on UNIX; in the path on Win32).</p>
- <p>OwnId:
- OTP-4676</p>
- </item>
- <item>
- <p>The new functions <c>ssl:peercert/1/2</c> provide information
- from the certificate of a peer of a connection.</p>
- <p>OwnId: OTP-4680
- <br></br>
-Aux Id: seq7688</p>
- </item>
- <item>
- <p>The function <c>ssl:port/1</c> has been removed from the
- documentation, but not from the <c>ssl</c> interface module.
- The recommendation is to use <c>ssl:peername/1</c>
- instead, which provides both address and port of the peer.</p>
- <p>OwnId: OTP-4681 </p>
- </item>
- <item>
- <p>New User's Guide documentation has been added.</p>
- <p>OwnId: OTP-4682 </p>
- </item>
- <item>
- <p>The old <c>ssl_socket</c> interface has been removed and also
- the documentation of it. </p>
- <p>OwnId: OTP-4683 </p>
- </item>
- <item>
- <p>The use of ephemeral RSA keys is now supported. It is
- a global configuration option (see the ssl(6) manual page).</p>
- <p>OwnId: OTP-4691.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The option <c>cacertfile</c> is now in effect, and can
- therefore no longer be set with the OS environment
- variable SSL_CERT_FILE (which did set the same value for
- all connections). </p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>There was a synchronization error at closing of an SSL
- connection. </p>
- <p>OwnId: OTP-4435
- <br></br>
-Aux Id: seq7534</p>
- </item>
- <item>
- <p>C macros in <c>debuglog.c</c> were not ANSI C compliant.</p>
- <p>OwnId: OTP-4674</p>
- </item>
- <item>
- <p>The <c>binary</c> option was not properly handled.</p>
- <p>OwnId: OTP-4678</p>
- </item>
- <item>
- <p>The <c>ssl:format_error/1</c> did not consider <c>inet</c>
- error codes, nor did it have a catch all for unknown error
- codes.</p>
- <p>OwnId: OTP-4679</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <list type="bulleted">
- <item>
- <p>Change of controlling process in not OTP compliant. </p>
- <p>OwnId; OTP-4712</p>
- </item>
- <item>
- <p>There is still no way to restrict the cipher sizes. </p>
- <p>OwnId: OTP-4712</p>
- </item>
- <item>
- <p>The <c>keep_alive</c> and <c>reuse_addr</c> options will be
- added in a future release. </p>
- <p>OwnId: OTP-4677</p>
- </item>
- <item>
- <p>There is currently no way to restrict the SSL/TLS
- protocol versions to use. In a future release this will be
- supported as a configuration option, and as an option for
- each connection as well. </p>
- <p>OwnId: OTP-4711.</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.6</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>There was a synchronization error at closing, which could
- result in that an SSL socket was removed prematurely, resulting
- in that a user process referring to it received an unexpected
- exit.</p>
- <p>OwnId: OTP-4435
- <br></br>
-Aux Id: seq7600</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <p>See SSL 2.2 . </p>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.5</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Setting of the option `nodelay' caused the SSL port program
- to dump core.</p>
- <p>OwnId: OTP-4380
- <br></br>
-Aux Id: -</p>
- </item>
- <item>
- <p>Setting of the option '{active, once}' in <c>setopts</c> was
- wrong, causing a correct socket message to be regarded as
- erroneous. </p>
- <p>OwnId: OTP-4380
- <br></br>
-Aux Id: -</p>
- </item>
- <item>
- <p>A self-signed peer certificate was always rejected with the
- error `eselfsignedcert', irrespective of the `depth' value. </p>
- <p>OwnId: OTP-4374
- <br></br>
-Aux Id: seq7417</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <p>See SSL 2.2 . </p>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>All TCP options allowed in gen_tcp, are now also allowed in
- SSL, except the option <c>{reuseaddr, Boolean}</c>. A new
- function <c>getopts</c> has been added to the SSL interface
- module <c>ssl</c>. </p>
- <p>OwnId: OTP-4305, OTP-4159</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.3</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The roles of the SSLeay and OpenSSL packages has been
- clarified in the ssl(6) application manual page. Also
- the URLs from which to download SSLeay has been updated.</p>
- <p>OwnId: OTP-4002
- <br></br>
-Aux Id: seq5269</p>
- </item>
- <item>
- <p>A call to <c>ssl:listen(Port, Options)</c> with
- <c>Options = []</c> resulted in the cryptic <c>{error, ebadf}</c> return value. The return value has been changed
- to <c>{error, enooptions}</c>, and the behaviour has been
- documented in the <c>listen/2</c> function.</p>
- <p>OwnId: OTP-4016
- <br></br>
-Aux Id: seq7006</p>
- </item>
- <item>
- <p>Use of the option <c>{nodelay, boolean()}</c> crashed
- the <c>ssl_server</c>.</p>
- <p>OwnId: OTP-4070
- <br></br>
-Aux Id:</p>
- </item>
- <item>
- <p>A bug caused the Erlang distribution over ssl to fail.
- This bug has now been fixed.</p>
- <p>OwnId: OTP-4072
- <br></br>
-Aux Id:</p>
- </item>
- <item>
- <p>On Windows when the SSL port program encountered an
- error code not anticipated it crashed. </p>
- <p>OwnId: OTP-4132
- <br></br>
-Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.2</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The <c>ssl:accept/1-2</c> function sometimes returned
- <c>{error, {What, Where}}</c> instead of <c>{error, What}</c>, where <c>What</c> is an atom. </p>
- <p>OwnId: OTP-3775
- <br></br>
-Aux Id: seq4991</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Sometimes the SSL portprogram would loop in an accept
- loop, without terminating even when the SSL application
- was stopped.. </p>
- <p>OwnId: OTP-3691</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.3</title>
- <p>Functions have been added to SSL to experimentally support
- Erlang distribution.
- </p>
- </section>
-
- <section>
- <title>SSL 2.2.1</title>
- <p>The 2.2.1 version of SSL provides code replacement in runtime
- by upgrading from, or downgrading to, versions 2.1 and 2.2.
- </p>
- </section>
-
- <section>
- <title>SSL 2.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The restriction that only the creator of an SSL socket can
- read from and write to the socket has been lifted.</p>
- <p>OwnId: OTP-3301</p>
- </item>
- <item>
- <p>The option <c>{packet, cdr}</c> for SSL sockets has been added,
- which means that SSL sockets also supports CDR encoded packets.</p>
- <p>OwnId: OTP-3302</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <list type="bulleted">
- <item>
- <p>Setting of a CA certificate file with the <c>cacertfile</c>
- option (in calls to <c>ssl:accept/1/2</c> or
- <c>ssl:connect/3/4</c>) does not work due to weaknesses
- in the SSLeay package. </p>
- <p>A work-around is to set the OS environment variable
- <c>SSL_CERT_FILE</c> before SSL is started. However, then
- the CA certificate file will be global for all connections.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>When changing controlling process of an SSL socket, a
- temporary process is started, which is not gen_server
- compliant.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>Although there is a <c>cache</c> timeout option, it is
- silently ignored.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>There is currently no way to restrict the cipher sizes.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The set of possible error reasons has been extended to
- contain diagnostics on erroneous certificates and failures
- to verify certificates.</p>
- <p>OwnId: OTP-3145</p>
- </item>
- <item>
- <p>The maximum number of simultaneous SSL connections on
- Windows has been increased from 31 to 127.</p>
- <p>OwnId: OTP-3145</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>A dead-lock occurring when write queues are not empty has
- been removed. </p>
- <p>OwnId: OTP-3145</p>
- </item>
- <item>
- <p>Error reasons have been unified and changed.</p>
- <p>(** POTENTIAL INCOMPATIBILITY **)</p>
- <p>OwnId: OTP-3145</p>
- </item>
- <item>
- <p>On Windows a check of the existence of the environment
- variable <c>ERLSRV_SERVICE_NAME</c> has been added. If
- that variable is defined, the port program of the SSL
- application will not terminated when a user logs off.</p>
- <p>OwnId: OTP-3145</p>
- </item>
- <item>
- <p>An error in the setting of the <c>nodelay</c> option
- has been corrected.</p>
- <p>OwnId: OTP-3145</p>
- </item>
- <item>
- <p>The confounded notions of verify mode and verify depth has
- been corrected. The option <c>verifydepth</c> has been
- removed, and the two separate options <c>verify</c> and
- <c>depth</c> has been added.</p>
- <p>(** POTENTIAL INCOMPATIBILITY **)</p>
- <p>OwnId: OTP-3145</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Known Bugs and Problems</title>
- <list type="bulleted">
- <item>
- <p>Setting of a CA certificate file with the <c>cacertfile</c>
- option (in calls to <c>ssl:accept/1/2</c> or
- <c>ssl:connect/3/4</c>) does not work due to weaknesses
- in the SSLeay package. </p>
- <p>A work-around is to set the OS environment variable
- <c>SSL_CERT_FILE</c> before SSL is started. However, then
- the CA certificate file will be global for all connections.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>When changing controlling process of an SSL socket, a
- temporary process is started, which is not gen_server
- compliant.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>Although there is a <c>cache</c> timeout option, it is
- silently ignored.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- <item>
- <p>There is currently no way to restrict the cipher sizes.</p>
- <p>OwnId: OTP-3146</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>SSL 2.0</title>
- <p>A complete new version of SSL with separate I/O channels
- for all connections with non-blocking I/O multiplexing.</p>
- </section>
</chapter>
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 9b1227fa7f..76e14860ec 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,24 +1,13 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"5.1.1", [{restart_application, ssl}]
- },
- {"5.1", [
- {load_module, ssl_connection, soft_purge, soft_purge, []}
- ]
- },
+ {<<"5.1\\*">>, [{restart_application, ssl}]},
{<<"5.0\\*">>, [{restart_application, ssl}]},
{<<"4\\.*">>, [{restart_application, ssl}]},
{<<"3\\.*">>, [{restart_application, ssl}]}
],
[
- {"5.1.1", [{restart_application, ssl}]
- },
- {"5.1", [
- {load_module, ssl_connection, soft_purge, soft_purge, []}
- ]
- },
- {"5.1", [{restart_application, ssl}]},
+ {<<"5.1\\*">>, [{restart_application, ssl}]},
{<<"5.0\\*">>, [{restart_application, ssl}]},
{<<"4\\.*">>, [{restart_application, ssl}]},
{<<"3\\.*">>, [{restart_application, ssl}]}
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index 222b3f1ad7..f94a1136a0 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,8 +36,7 @@
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec reason_code(#alert{}, client | server) -> closed | esslconnect |
- esslaccept | string().
+-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}.
%%
%% Description: Returns the error reason that will be returned to the
%% user.
@@ -45,12 +44,8 @@
reason_code(#alert{description = ?CLOSE_NOTIFY}, _) ->
closed;
-reason_code(#alert{description = ?HANDSHAKE_FAILURE}, client) ->
- esslconnect;
-reason_code(#alert{description = ?HANDSHAKE_FAILURE}, server) ->
- esslaccept;
reason_code(#alert{description = Description}, _) ->
- description_txt(Description).
+ {essl, description_txt(Description)}.
%%--------------------------------------------------------------------
-spec alert_txt(#alert{}) -> string().
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index cde13069b5..68f6a4d4c1 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1135,7 +1135,7 @@ init_certificates(#ssl_options{cacerts = CaCerts,
{ok, _, _, _, _, _} = ssl_manager:connection_init(Certs, Role)
catch
Error:Reason ->
- handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile,
+ handle_file_error(?LINE, Error, Reason, CACertFile, {ecacertfile, Reason},
erlang:get_stacktrace())
end,
init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, CertFile, Role).
@@ -1157,7 +1157,7 @@ init_certificates(undefined, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHan
{ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, OwnCert}
catch
Error:Reason ->
- handle_file_error(?LINE, Error, Reason, CertFile, ecertfile,
+ handle_file_error(?LINE, Error, Reason, CertFile, {ecertfile, Reason},
erlang:get_stacktrace())
end;
init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, _, _) ->
@@ -1176,7 +1176,7 @@ init_private_key(DbHandle, undefined, KeyFile, Password, _) ->
private_key(public_key:pem_entry_decode(PemEntry, Password))
catch
Error:Reason ->
- handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile,
+ handle_file_error(?LINE, Error, Reason, KeyFile, {ekeyfile, Reason},
erlang:get_stacktrace())
end;
@@ -1234,7 +1234,7 @@ init_diffie_hellman(DbHandle,_, DHParamFile, server) ->
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason,
- DHParamFile, edhfile, erlang:get_stacktrace())
+ DHParamFile, {edhfile, Reason}, erlang:get_stacktrace())
end.
sync_send_all_state_event(FsmPid, Event) ->
@@ -1628,78 +1628,49 @@ save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, abbrev
save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, abbreviated) ->
ssl_record:set_server_verify_data(current_write, Data, ConnectionStates).
-handle_server_key(#server_key_exchange{params =
- #server_dh_params{dh_p = P,
- dh_g = G,
- dh_y = ServerPublicDhKey},
- signed_params = <<>>},
- #state{key_algorithm = dh_anon} = State) ->
- dh_master_secret(P, G, ServerPublicDhKey, undefined, State);
-
-handle_server_key(
- #server_key_exchange{params =
- #server_dh_params{dh_p = P,
- dh_g = G,
- dh_y = ServerPublicDhKey},
- signed_params = Signed,
- hashsign = HashSign},
- #state{negotiated_version = Version,
- public_key_info = PubKeyInfo,
- connection_states = ConnectionStates} = State) ->
-
- PLen = size(P),
- GLen = size(G),
- YLen = size(ServerPublicDhKey),
- HashAlgo = connection_hash_algo(HashSign, State),
+handle_server_key(#server_key_exchange{exchange_keys = Keys},
+ #state{key_algorithm = KeyAlg,
+ negotiated_version = Version} = State) ->
+ Params = ssl_handshake:decode_server_key(Keys, KeyAlg, Version),
+ HashSign = connection_hashsign(Params#server_key_params.hashsign, State),
+ case HashSign of
+ {_, anon} ->
+ server_master_secret(Params#server_key_params.params, State);
+ _ ->
+ verify_server_key(Params, HashSign, State)
+ end.
- ConnectionState =
+verify_server_key(#server_key_params{params = Params,
+ params_bin = EncParams,
+ signature = Signature},
+ HashSign = {HashAlgo, _},
+ #state{negotiated_version = Version,
+ public_key_info = PubKeyInfo,
+ connection_states = ConnectionStates} = State) ->
+ ConnectionState =
ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
Hash = ssl_handshake:server_key_exchange_hash(HashAlgo,
- <<ClientRandom/binary,
- ServerRandom/binary,
- ?UINT16(PLen), P/binary,
- ?UINT16(GLen), G/binary,
- ?UINT16(YLen),
- ServerPublicDhKey/binary>>),
-
- case verify_dh_params(Version, Signed, Hash, HashAlgo, PubKeyInfo) of
+ <<ClientRandom/binary,
+ ServerRandom/binary,
+ EncParams/binary>>),
+ case ssl_handshake:verify_signature(Version, Hash, HashSign, Signature, PubKeyInfo) of
true ->
- dh_master_secret(P, G, ServerPublicDhKey, undefined, State);
+ server_master_secret(Params, State);
false ->
?ALERT_REC(?FATAL, ?DECRYPT_ERROR)
end.
-verify_dh_params({3, Minor}, Signed, Hashes, HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams})
- when Minor >= 3 ->
- public_key:verify({digest, Hashes}, HashAlgo, Signed, PubKey);
-verify_dh_params(_Version, Signed, Hashes, _HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams}) ->
- case public_key:decrypt_public(Signed, PubKey,
- [{rsa_pad, rsa_pkcs1_padding}]) of
- Hashes ->
- true;
- _ ->
- false
- end;
-verify_dh_params(_Version, Signed, Hash, HashAlgo, {?'id-dsa', PublicKey, PublicKeyParams}) ->
- public_key:verify({digest, Hash}, HashAlgo, Signed, {PublicKey, PublicKeyParams}).
-
-dh_master_secret(Prime, Base, PublicDhKey, undefined, State) ->
- PMpint = mpint_binary(Prime),
- GMpint = mpint_binary(Base),
- Keys = {_, PrivateDhKey} =
- crypto:dh_generate_key([PMpint,GMpint]),
- dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys});
+server_master_secret(#server_dh_params{dh_p = P, dh_g = G, dh_y = ServerPublicDhKey},
+ State) ->
+ dh_master_secret(P, G, ServerPublicDhKey, undefined, State).
-dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey,
- #state{session = Session,
- negotiated_version = Version, role = Role,
- connection_states = ConnectionStates0} = State) ->
- PremasterSecret =
- crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey,
- [PMpint, GMpint]),
+master_from_premaster_secret(PremasterSecret,
+ #state{session = Session,
+ negotiated_version = Version, role = Role,
+ connection_states = ConnectionStates0} = State) ->
case ssl_handshake:master_secret(Version, PremasterSecret,
ConnectionStates0, Role) of
{MasterSecret, ConnectionStates} ->
@@ -1711,6 +1682,19 @@ dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey,
Alert
end.
+dh_master_secret(Prime, Base, PublicDhKey, undefined, State) ->
+ PMpint = mpint_binary(Prime),
+ GMpint = mpint_binary(Base),
+ Keys = {_, PrivateDhKey} =
+ crypto:dh_generate_key([PMpint,GMpint]),
+ dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys});
+
+dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State) ->
+ PremasterSecret =
+ crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey,
+ [PMpint, GMpint]),
+ master_from_premaster_secret(PremasterSecret, State).
+
cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) ->
ConnectionStates = ssl_record:set_server_verify_data(current_both, Data, ConnectionStates0),
next_state_connection(cipher, ack_connection(State#state{session = Session,
@@ -2485,10 +2469,10 @@ get_pending_connection_state_prf(CStates, Direction) ->
CS = ssl_record:pending_connection_state(CStates, Direction),
CS#connection_state.security_parameters#security_parameters.prf_algorithm.
-connection_hash_algo({HashAlgo, _}, _State) ->
- HashAlgo;
-connection_hash_algo(_, #state{hashsign_algorithm = {HashAlgo, _}}) ->
- HashAlgo.
+connection_hashsign(HashSign = {_, _}, _State) ->
+ HashSign;
+connection_hashsign(_, #state{hashsign_algorithm = HashSign}) ->
+ HashSign.
%% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms
%% If the client does not send the signature_algorithms extension, the
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index db21dac942..1929370991 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -32,10 +32,10 @@
-export([master_secret/4, client_hello/8, server_hello/5, hello/4,
hello_request/0, certify/7, certificate/4,
- client_certificate_verify/6, certificate_verify/6,
+ client_certificate_verify/6, certificate_verify/6, verify_signature/5,
certificate_request/3, key_exchange/3, server_key_exchange_hash/2,
finished/5, verify_connection/6, get_tls_handshake/3,
- decode_client_key/3, server_hello_done/0,
+ decode_client_key/3, decode_server_key/3, server_hello_done/0,
encode_handshake/2, init_handshake_history/0, update_handshake_history/2,
decrypt_premaster_secret/2, prf/5, next_protocol/1]).
@@ -320,25 +320,36 @@ client_certificate_verify(OwnCert, MasterSecret, Version,
%%
%% Description: Checks that the certificate_verify message is valid.
%%--------------------------------------------------------------------
-certificate_verify(Signature, {?'rsaEncryption', PublicKey, _}, Version,
- {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) ->
- Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
- case certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, Version) of
+certificate_verify(Signature, PublicKeyInfo, Version,
+ HashSign = {HashAlgo, _}, MasterSecret, {_, Handshake}) ->
+ Hash = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
+ case verify_signature(Version, Hash, HashSign, Signature, PublicKeyInfo) of
true ->
valid;
_ ->
- ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE)
- end;
-certificate_verify(Signature, {?'id-dsa', PublicKey, PublicKeyParams}, Version,
- {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) ->
- Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
- case public_key:verify({digest, Hashes}, sha, Signature, {PublicKey, PublicKeyParams}) of
- true ->
- valid;
- false ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE)
end.
+%%--------------------------------------------------------------------
+-spec verify_signature(tls_version(), binary(), {term(), term()}, binary(),
+ public_key_info()) -> true | false.
+%%
+%% Description: Checks that a public_key signature is valid.
+%%--------------------------------------------------------------------
+verify_signature(_Version, _Hash, {_HashAlgo, anon}, _Signature, _) ->
+ true;
+verify_signature({3, Minor}, Hash, {HashAlgo, rsa}, Signature, {?rsaEncryption, PubKey, _PubKeyParams})
+ when Minor >= 3 ->
+ public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey);
+verify_signature(_Version, Hash, _HashAlgo, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) ->
+ case public_key:decrypt_public(Signature, PubKey,
+ [{rsa_pad, rsa_pkcs1_padding}]) of
+ Hash -> true;
+ _ -> false
+ end;
+verify_signature(_Version, Hash, {HashAlgo, dsa}, Signature, {?'id-dsa', PublicKey, PublicKeyParams}) ->
+ public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}).
+
%%--------------------------------------------------------------------
-spec certificate_request(#connection_states{}, db_handle(), certdb_ref()) ->
@@ -382,31 +393,33 @@ key_exchange(client, _Version, {dh, <<?UINT32(Len), PublicKey:Len/binary>>}) ->
key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
#'DHParameter'{prime = P, base = G},
- {HashAlgo, SignAlgo}, ClientRandom, ServerRandom, PrivateKey}) ->
+ HashSign, ClientRandom, ServerRandom, PrivateKey}) ->
<<?UINT32(_), PBin/binary>> = crypto:mpint(P),
<<?UINT32(_), GBin/binary>> = crypto:mpint(G),
- PLen = byte_size(PBin),
- GLen = byte_size(GBin),
- YLen = byte_size(PublicKey),
ServerDHParams = #server_dh_params{dh_p = PBin,
dh_g = GBin, dh_y = PublicKey},
+ enc_server_key_exchange(Version, ServerDHParams, HashSign,
+ ClientRandom, ServerRandom, PrivateKey).
+enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo},
+ ClientRandom, ServerRandom, PrivateKey) ->
+ EncParams = enc_server_key(Params),
case HashAlgo of
null ->
- #server_key_exchange{params = ServerDHParams,
- signed_params = <<>>,
- hashsign = {null, anon}};
+ #server_key_params{params = Params,
+ params_bin = EncParams,
+ hashsign = {null, anon},
+ signature = <<>>};
_ ->
Hash =
server_key_exchange_hash(HashAlgo, <<ClientRandom/binary,
- ServerRandom/binary,
- ?UINT16(PLen), PBin/binary,
- ?UINT16(GLen), GBin/binary,
- ?UINT16(YLen), PublicKey/binary>>),
- Signed = digitally_signed(Version, Hash, HashAlgo, PrivateKey),
- #server_key_exchange{params = ServerDHParams,
- signed_params = Signed,
- hashsign = {HashAlgo, SignAlgo}}
+ ServerRandom/binary,
+ EncParams/binary>>),
+ Signature = digitally_signed(Version, Hash, HashAlgo, PrivateKey),
+ #server_key_params{params = Params,
+ params_bin = EncParams,
+ hashsign = {HashAlgo, SignAlgo},
+ signature = Signature}
end.
%%--------------------------------------------------------------------
@@ -523,6 +536,15 @@ decode_client_key(ClientKey, Type, Version) ->
dec_client_key(ClientKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
+-spec decode_server_key(binary(), key_algo(), tls_version()) ->
+ #server_key_params{}.
+%%
+%% Description: Decode server_key data and return appropriate type
+%%--------------------------------------------------------------------
+decode_server_key(ServerKey, Type, Version) ->
+ dec_server_key(ServerKey, key_exchange_alg(Type), Version).
+
+%%--------------------------------------------------------------------
-spec init_handshake_history() -> tls_handshake_history().
%%
@@ -975,31 +997,8 @@ dec_hs(_Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
next_protocol_negotiation = NextProtocolNegotiation};
dec_hs(_Version, ?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) ->
#certificate{asn1_certificates = certs_to_list(ASN1Certs)};
-
-dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?UINT16(YLen), Y:YLen/binary,
- ?UINT16(0)>>) -> %% May happen if key_algorithm is dh_anon
- #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
- dh_y = Y},
- signed_params = <<>>, hashsign = {null, anon}};
-dec_hs({Major, Minor}, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?UINT16(YLen), Y:YLen/binary,
- ?BYTE(HashAlgo), ?BYTE(SignAlgo),
- ?UINT16(Len), Sig:Len/binary>>)
- when Major == 3, Minor >= 3 ->
- #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
- dh_y = Y},
- signed_params = Sig,
- hashsign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}};
-dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?UINT16(YLen), Y:YLen/binary,
- ?UINT16(Len), Sig:Len/binary>>) ->
- #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
- dh_y = Y},
- signed_params = Sig, hashsign = undefined};
+dec_hs(_Version, ?SERVER_KEY_EXCHANGE, Keys) ->
+ #server_key_exchange{exchange_keys = Keys};
dec_hs({Major, Minor}, ?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary,
@@ -1039,6 +1038,42 @@ dec_client_key(<<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>,
?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
#client_diffie_hellman_public{dh_public = DH_Y}.
+dec_ske_params(Len, Keys, Version) ->
+ <<Params:Len/bytes, Signature/binary>> = Keys,
+ dec_ske_signature(Params, Signature, Version).
+
+dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo),
+ ?UINT16(0)>>, {Major, Minor})
+ when Major == 3, Minor >= 3 ->
+ HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)},
+ {Params, HashSign, <<>>};
+dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo),
+ ?UINT16(Len), Signature:Len/binary>>, {Major, Minor})
+ when Major == 3, Minor >= 3 ->
+ HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)},
+ {Params, HashSign, Signature};
+dec_ske_signature(Params, <<>>, _) ->
+ {Params, {null, anon}, <<>>};
+dec_ske_signature(Params, <<?UINT16(0)>>, _) ->
+ {Params, {null, anon}, <<>>};
+dec_ske_signature(Params, <<?UINT16(Len), Signature:Len/binary>>, _) ->
+ {Params, undefined, Signature};
+dec_ske_signature(_, _, _) ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)).
+
+dec_server_key(<<?UINT16(PLen), P:PLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_DIFFIE_HELLMAN, Version) ->
+ Params = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y},
+ {BinMsg, HashSign, Signature} = dec_ske_params(PLen + GLen + YLen + 6, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(_, _, _) ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)).
+
dec_hello_extensions(<<>>) ->
[];
dec_hello_extensions(<<?UINT16(ExtLen), Extensions:ExtLen/binary>>) ->
@@ -1156,18 +1191,12 @@ enc_hs(#certificate{asn1_certificates = ASN1CertList}, _Version) ->
ASN1Certs = certs_from_list(ASN1CertList),
ACLen = erlang:iolist_size(ASN1Certs),
{?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>};
-enc_hs(#server_key_exchange{params = #server_dh_params{
- dh_p = P, dh_g = G, dh_y = Y},
- signed_params = SignedParams, hashsign = HashSign}, Version) ->
- PLen = byte_size(P),
- GLen = byte_size(G),
- YLen = byte_size(Y),
- Signature = enc_sign(HashSign, SignedParams, Version),
- {?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P/binary,
- ?UINT16(GLen), G/binary,
- ?UINT16(YLen), Y/binary,
- Signature/binary>>
- };
+enc_hs(#server_key_exchange{exchange_keys = Keys}, _Version) ->
+ {?SERVER_KEY_EXCHANGE, Keys};
+enc_hs(#server_key_params{params_bin = Keys, hashsign = HashSign,
+ signature = Signature}, Version) ->
+ EncSign = enc_sign(HashSign, Signature, Version),
+ {?SERVER_KEY_EXCHANGE, <<Keys/binary, EncSign/binary>>};
enc_hs(#certificate_request{certificate_types = CertTypes,
hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
certificate_authorities = CertAuths},
@@ -1211,6 +1240,14 @@ enc_cke(#client_diffie_hellman_public{dh_public = DHPublic}, _) ->
Len = byte_size(DHPublic),
<<?UINT16(Len), DHPublic/binary>>.
+enc_server_key(#server_dh_params{dh_p = P, dh_g = G, dh_y = Y}) ->
+ PLen = byte_size(P),
+ GLen = byte_size(G),
+ YLen = byte_size(Y),
+ <<?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>.
+
+enc_sign({_, anon}, _Sign, _Version) ->
+ <<>>;
enc_sign({HashAlg, SignAlg}, Signature, _Version = {Major, Minor})
when Major == 3, Minor >= 3->
SignLen = byte_size(Signature),
@@ -1328,8 +1365,8 @@ certificate_authorities_from_db(CertDbHandle, CertDbRef) ->
digitally_signed({3, Minor}, Hash, HashAlgo, Key) when Minor >= 3 ->
public_key:sign({digest, Hash}, HashAlgo, Key);
-digitally_signed(_Version, Hash, _HashAlgo, #'DSAPrivateKey'{} = Key) ->
- public_key:sign({digest, Hash}, sha, Key);
+digitally_signed(_Version, Hash, HashAlgo, #'DSAPrivateKey'{} = Key) ->
+ public_key:sign({digest, Hash}, HashAlgo, Key);
digitally_signed(_Version, Hash, _HashAlgo, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
[{rsa_pad, rsa_pkcs1_padding}]).
@@ -1378,19 +1415,6 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) ->
{unknown, {SslState, UserState}}
end.
-certificate_verify_rsa(Hashes, sha, Signature, PublicKey, {Major, Minor})
- when Major == 3, Minor >= 3 ->
- public_key:verify({digest, Hashes}, sha, Signature, PublicKey);
-certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, {Major, Minor})
- when Major == 3, Minor >= 3 ->
- public_key:verify({digest, Hashes}, HashAlgo, Signature, PublicKey);
-certificate_verify_rsa(Hashes, _HashAlgo, Signature, PublicKey, _Version) ->
- case public_key:decrypt_public(Signature, PublicKey,
- [{rsa_pad, rsa_pkcs1_padding}]) of
- Hashes -> true;
- _ -> false
- end.
-
-define(TLSEXT_SIGALG_RSA(MD), {MD, rsa}).
-define(TLSEXT_SIGALG_DSA(MD), {MD, dsa}).
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index 9af6511d68..2414d5b666 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -141,9 +141,14 @@
}).
-record(server_key_exchange, {
+ exchange_keys
+ }).
+
+-record(server_key_params, {
params, %% #server_rsa_params{} | #server_dh_params{}
- signed_params, %% #signature{}
- hashsign %% term(atom(), atom())
+ params_bin,
+ hashsign, %% term(atom(), atom())
+ signature %% #signature{}
}).
%% enum { anonymous, rsa, dsa } SignatureAlgorithm;
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 13689ce7d8..14fba72d86 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -142,8 +142,14 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
new_session_id(Port) ->
call({new_session_id, Port}).
+%%--------------------------------------------------------------------
+-spec clean_cert_db(reference(), binary()) -> term().
+%%
+%% Description: Send clean request of cert db to ssl_manager process should
+%% be called by ssl-connection processes.
+%%--------------------------------------------------------------------
clean_cert_db(Ref, File) ->
- erlang:send_after(?CLEAN_CERT_DB, self(), {clean_cert_db, Ref, File}).
+ erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager), {clean_cert_db, Ref, File}).
%%--------------------------------------------------------------------
-spec register_session(inet:port_number(), #session{}) -> ok.
@@ -320,19 +326,12 @@ handle_info(clear_pem_cache, #state{certificate_db = [_,_,PemChace]} = State) ->
handle_info({clean_cert_db, Ref, File},
#state{certificate_db = [CertDb,RefDb, PemCache]} = State) ->
- case ssl_certificate_db:ref_count(Ref, RefDb, 0) of
- 0 ->
- MD5 = crypto:md5(File),
- case ssl_certificate_db:lookup_cached_pem(PemCache, MD5) of
- [{Content, Ref}] ->
- ssl_certificate_db:insert(MD5, Content, PemCache);
- undefined ->
- ok
- end,
- ssl_certificate_db:remove(Ref, RefDb),
- ssl_certificate_db:remove_trusted_certs(Ref, CertDb);
+
+ case ssl_certificate_db:lookup(Ref, RefDb) of
+ undefined -> %% Alredy cleaned
+ ok;
_ ->
- ok
+ clean_cert_db(Ref, CertDb, RefDb, PemCache, File)
end,
{noreply, State};
@@ -464,3 +463,19 @@ new_id(Port, Tries, Cache, CacheCb) ->
_ ->
new_id(Port, Tries - 1, Cache, CacheCb)
end.
+
+clean_cert_db(Ref, CertDb, RefDb, PemCache, File) ->
+ case ssl_certificate_db:ref_count(Ref, RefDb, 0) of
+ 0 ->
+ MD5 = crypto:md5(File),
+ case ssl_certificate_db:lookup_cached_pem(PemCache, MD5) of
+ [{Content, Ref}] ->
+ ssl_certificate_db:insert(MD5, Content, PemCache);
+ _ ->
+ ok
+ end,
+ ssl_certificate_db:remove(Ref, RefDb),
+ ssl_certificate_db:remove_trusted_certs(Ref, CertDb);
+ _ ->
+ ok
+ end.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 5ba71f9218..df84acacdc 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -84,7 +84,8 @@ basic_tests() ->
alerts,
send_close,
connect_twice,
- connect_dist
+ connect_dist,
+ clear_pem_cache
].
options_tests() ->
@@ -536,6 +537,33 @@ connect_dist(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+
+clear_pem_cache() ->
+ [{doc,"Test that internal reference tabel is cleaned properly even when "
+ " the PEM cache is cleared" }].
+clear_pem_cache(Config) when is_list(Config) ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ [_,FilRefDb, _] = element(5, State),
+ {Server, Client} = basic_verify_test_no_close(Config),
+ 2 = ets:info(FilRefDb, size),
+ ssl:clear_pem_cache(),
+ _ = sys:get_status(whereis(ssl_manager)),
+ {Server1, Client1} = basic_verify_test_no_close(Config),
+ 4 = ets:info(FilRefDb, size),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ ct:sleep(5000),
+ _ = sys:get_status(whereis(ssl_manager)),
+ 2 = ets:info(FilRefDb, size),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1),
+ ct:sleep(5000),
+ _ = sys:get_status(whereis(ssl_manager)),
+ 0 = ets:info(FilRefDb, size).
+
+%%--------------------------------------------------------------------
peername() ->
[{doc,"Test API function peername/1"}].
@@ -1567,8 +1595,8 @@ default_reject_anonymous(Config) when is_list(Config) ->
[{ciphers,[Cipher]} |
ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, "insufficient security"},
- Client, {error, "insufficient security"}).
+ ssl_test_lib:check_result(Server, {error, {essl, "insufficient security"}},
+ Client, {error, {essl, "insufficient security"}}).
%%--------------------------------------------------------------------
reuse_session() ->
@@ -2641,6 +2669,26 @@ tcp_send_recv_result(Socket) ->
{ok,"Hello world"} = gen_tcp:recv(Socket, 11),
ok.
+basic_verify_test_no_close(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ {Server, Client}.
+
basic_test(Config) ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
@@ -2659,7 +2707,6 @@ basic_test(Config) ->
{options, ClientOpts}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
-
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 9677d98c1b..86e1d47be7 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -252,8 +252,8 @@ server_require_peer_cert_fail(Config) when is_list(Config) ->
{from, self()},
{options, [{active, false} | BadClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, esslaccept},
- Client, {error, esslconnect}).
+ ssl_test_lib:check_result(Server, {error, {essl, "handshake failure"}},
+ Client, {error, {essl, "handshake failure"}}).
%%--------------------------------------------------------------------
@@ -293,14 +293,14 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
[{verify, verify_peer},
{verify_fun, FunAndState}
| ClientOpts]}]),
- %% Server error may be esslaccept or closed depending on timing
+ %% Server error may be {essl,"handshake failure"} or closed depending on timing
%% this is not a bug it is a circumstance of how tcp works!
receive
{Server, ServerError} ->
ct:print("Server Error ~p~n", [ServerError])
end,
- ssl_test_lib:check_result(Client, {error, esslconnect}).
+ ssl_test_lib:check_result(Client, {error, {essl, "handshake failure"}}).
%%--------------------------------------------------------------------
verify_fun_always_run_server() ->
@@ -342,14 +342,14 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
[{verify, verify_peer}
| ClientOpts]}]),
- %% Client error may be esslconnect or closed depending on timing
+ %% Client error may be {essl, "handshake failure" } or closed depending on timing
%% this is not a bug it is a circumstance of how tcp works!
receive
{Client, ClientError} ->
ct:print("Client Error ~p~n", [ClientError])
end,
- ssl_test_lib:check_result(Server, {error, esslaccept}).
+ ssl_test_lib:check_result(Server, {error, {essl, "handshake failure"}}).
%%--------------------------------------------------------------------
@@ -380,7 +380,7 @@ client_verify_none_passive(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
cert_expired() ->
- [{doc,"Test server with invalid signature"}].
+ [{doc,"Test server with expired certificate"}].
cert_expired(Config) when is_list(Config) ->
ClientOpts = ?config(client_verification_opts, Config),
@@ -432,8 +432,8 @@ cert_expired(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, "certificate expired"},
- Client, {error, "certificate expired"}).
+ ssl_test_lib:check_result(Server, {error, {essl, "certificate expired"}},
+ Client, {error, {essl, "certificate expired"}}).
two_digits_str(N) when N < 10 ->
lists:flatten(io_lib:format("0~p", [N]));
@@ -679,7 +679,7 @@ delete_authority_key_extension([Head | Rest], Acc) ->
%%--------------------------------------------------------------------
invalid_signature_server() ->
- [{doc,"Test server with invalid signature"}].
+ [{doc,"Test client with invalid signature"}].
invalid_signature_server(Config) when is_list(Config) ->
ClientOpts = ?config(client_verification_opts, Config),
@@ -710,8 +710,8 @@ invalid_signature_server(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- tcp_delivery_workaround(Server, {error, "bad certificate"},
- Client, {error,"bad certificate"}).
+ tcp_delivery_workaround(Server, {error, {essl, "bad certificate"}},
+ Client, {error, {essl, "bad certificate"}}).
%%--------------------------------------------------------------------
@@ -747,8 +747,8 @@ invalid_signature_client(Config) when is_list(Config) ->
{from, self()},
{options, NewClientOpts}]),
- tcp_delivery_workaround(Server, {error, "bad certificate"},
- Client, {error,"bad certificate"}).
+ tcp_delivery_workaround(Server, {error, {essl, "bad certificate"}},
+ Client, {error, {essl, "bad certificate"}}).
%%--------------------------------------------------------------------
@@ -829,8 +829,8 @@ unknown_server_ca_fail(Config) when is_list(Config) ->
{verify_fun, FunAndState}
| ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error,"unknown ca"},
- Client, {error, "unknown ca"}).
+ ssl_test_lib:check_result(Server, {error, {essl, "unknown ca"}},
+ Client, {error, {essl, "unknown ca"}}).
%%--------------------------------------------------------------------
unknown_server_ca_accept_verify_none() ->
@@ -947,10 +947,6 @@ tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
{Client, {error,closed}} ->
server_msg(Server, ServerMsg);
{Server, {error,closed}} ->
- client_msg(Client, ClientMsg);
- {Client, {error, esslconnect}} ->
- server_msg(Server, ServerMsg);
- {Server, {error, esslaccept}} ->
client_msg(Client, ClientMsg)
end.
@@ -961,8 +957,8 @@ client_msg(Client, ClientMsg) ->
{Client, {error,closed}} ->
ct:print("client got close"),
ok;
- {Client, {error, esslconnect}} ->
- ct:print("client got econnaborted"),
+ {Client, {error, Reason}} ->
+ ct:print("client got econnaborted: ~p", [Reason]),
ok;
Unexpected ->
ct:fail(Unexpected)
@@ -974,8 +970,8 @@ server_msg(Server, ServerMsg) ->
{Server, {error,closed}} ->
ct:print("server got close"),
ok;
- {Server, {error, esslaccept}} ->
- ct:print("server got econnaborted"),
+ {Server, {error, Reason}} ->
+ ct:print("server got econnaborted: ~p", [Reason]),
ok;
Unexpected ->
ct:fail(Unexpected)
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 76b302b1cb..8d96a70a6e 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -203,6 +203,67 @@ close(Pid) ->
ct:print("Pid: ~p down due to:~p ~n", [Pid, Reason])
end.
+
+check_result(Server, {error, SReason} = ServerMsg, Client, {error, closed} = ClientMsg) ->
+ receive
+ {Server, {error, {SReason, _}}} ->
+ receive
+ {Client, ClientMsg} ->
+ ok;
+ Unexpected ->
+ Reason = {{expected, {Client, ClientMsg}},
+ {got, Unexpected}},
+ ct:fail(Reason)
+ end;
+ {Client, ClientMsg} ->
+ receive
+ {Server, {error, {SReason, _}}} ->
+ ok;
+ Unexpected ->
+ Reason = {{expected, {Server,{error, {SReason, 'term()'}}},
+ {got, Unexpected}}},
+ ct:fail(Reason)
+ end;
+ {Port, {data,Debug}} when is_port(Port) ->
+ io:format("openssl ~s~n",[Debug]),
+ check_result(Server, ServerMsg, Client, ClientMsg);
+
+ Unexpected ->
+ Reason = {{expected, {Client, ClientMsg}},
+ {expected, {Server, {error, {SReason, 'term()'}}}, {got, Unexpected}}},
+ ct:fail(Reason)
+ end;
+
+check_result(Server, {error, closed} = ServerMsg, Client, {error, CReson} = ClientMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ receive
+ {Client, {error, {CReson, _}}} ->
+ ok;
+ Unexpected ->
+ Reason = {{expected, {Client, {error, {CReson, 'term()'}}},
+ {got, Unexpected}}},
+ ct:fail(Reason)
+ end;
+ {Client, {error, {CReson, _}}} ->
+ receive
+ {Server, ServerMsg} ->
+ ok;
+ Unexpected ->
+ Reason = {{expected, {Server, ServerMsg}},
+ {got, Unexpected}},
+ ct:fail(Reason)
+ end;
+ {Port, {data,Debug}} when is_port(Port) ->
+ io:format("openssl ~s~n",[Debug]),
+ check_result(Server, ServerMsg, Client, ClientMsg);
+
+ Unexpected ->
+ Reason = {{expected, {Client, {error, {CReson, 'term()'}}},
+ {expected, {Server, ServerMsg}}, {got, Unexpected}}},
+ ct:fail(Reason)
+ end;
+
check_result(Server, ServerMsg, Client, ClientMsg) ->
receive
{Server, ServerMsg} ->
@@ -233,6 +294,22 @@ check_result(Server, ServerMsg, Client, ClientMsg) ->
ct:fail(Reason)
end.
+check_result(Pid, {error, Reason} = Err) when Reason == ecertfile;
+ Reason == ecacertfile;
+ Reason == ekeyfile;
+ Reason == edhfile ->
+ receive
+ {Pid, {error, {Reason, Str}}} when is_list(Str) ->
+ ok;
+ {Port, {data,Debug}} when is_port(Port) ->
+ io:format("openssl ~s~n",[Debug]),
+ check_result(Pid, Err);
+ Unexpected ->
+ Reason = {{expected, {Pid, {error, {Reason, "'appropriate error string'"}}}},
+ {got, Unexpected}},
+ ct:fail(Reason)
+ end;
+
check_result(Pid, Msg) ->
receive
{Pid, Msg} ->
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index d5e7d515fd..7c0c00bf36 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -902,7 +902,7 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
ok
end,
- ssl_test_lib:check_result(Server, {error,"protocol version"}),
+ ssl_test_lib:check_result(Server, {error, {essl, "protocol version"}}),
process_flag(trap_exit, false).
%%--------------------------------------------------------------------
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index adfb29e639..cb73e86ede 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 5.1.2
+SSL_VSN = 5.2
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index 34c6ecc394..51def8c8e1 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -153,7 +153,6 @@ pattern({record,Line,Name,Pfs0}) ->
pattern({record_index,Line,Name,Field0}) ->
Field1 = pattern(Field0),
{record_index,Line,Name,Field1};
-%% record_field occurs in query expressions
pattern({record_field,Line,Rec0,Name,Field0}) ->
Rec1 = expr(Rec0),
Field1 = expr(Field0),
@@ -431,10 +430,6 @@ expr({'catch',Line,E0}) ->
%% No new variables added.
E1 = expr(E0),
{'catch',Line,E1};
-expr({'query', Line, E0}) ->
- %% lc expression
- E = expr(E0),
- {'query', Line, E};
expr({match,Line,P0,E0}) ->
E1 = expr(E0),
P1 = pattern(P0),
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index 5d800e87b8..0068d82d43 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,7 +28,7 @@
%% of (some) functions of this module.
%%-------------------------------------------------------------------------
--type ascii_string() :: [1..255].
+-type ascii_string() :: [1..127].
%%-------------------------------------------------------------------------
%% encode_to_string(ASCII) -> Base64String
diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl
index 1164ee49eb..3192879f09 100644
--- a/lib/stdlib/src/edlin.erl
+++ b/lib/stdlib/src/edlin.erl
@@ -22,10 +22,10 @@
%% A simple Emacs-like line editor.
%% About Latin-1 characters: see the beginning of erl_scan.erl.
--export([init/0,start/1,edit_line/2,prefix_arg/1]).
+-export([init/0,start/1,start/2,edit_line/2,prefix_arg/1]).
-export([erase_line/1,erase_inp/1,redraw_line/1]).
-export([length_before/1,length_after/1,prompt/1]).
--export([current_line/1]).
+-export([current_line/1, current_chars/1]).
%%-export([expand/1]).
-export([edit_line1/2]).
@@ -54,7 +54,12 @@ init() ->
%% {undefined,Char,Rest,Cont,Requests}
start(Pbs) ->
- {more_chars,{line,Pbs,{[],[]},none},[{put_chars,unicode,Pbs}]}.
+ start(Pbs, none).
+
+%% Only two modes used: 'none' and 'search'. Other modes can be
+%% handled inline through specific character handling.
+start(Pbs, Mode) ->
+ {more_chars,{line,Pbs,{[],[]},Mode},[{put_chars,unicode,Pbs}]}.
edit_line(Cs, {line,P,L,{blink,N}}) ->
edit(Cs, P, L, none, [{move_rel,N}]);
@@ -76,6 +81,10 @@ edit([C|Cs], P, {Bef,Aft}, Prefix, Rs0) ->
edit(Cs, P, {Bef,Aft}, meta, Rs0);
meta_left_sq_bracket ->
edit(Cs, P, {Bef,Aft}, meta_left_sq_bracket, Rs0);
+ search_meta ->
+ edit(Cs, P, {Bef,Aft}, search_meta, Rs0);
+ search_meta_left_sq_bracket ->
+ edit(Cs, P, {Bef,Aft}, search_meta_left_sq_bracket, Rs0);
ctlx ->
edit(Cs, P, {Bef,Aft}, ctlx, Rs0);
new_line ->
@@ -115,6 +124,8 @@ edit([C|Cs], P, {Bef,Aft}, Prefix, Rs0) ->
case do_op(Op, Bef, Aft, Rs0) of
{blink,N,Line,Rs} ->
edit(Cs, P, Line, {blink,N}, Rs);
+ {Line, Rs, Mode} -> % allow custom modes from do_op
+ edit(Cs, P, Line, Mode, Rs);
{Line,Rs} ->
edit(Cs, P, Line, none, Rs)
end
@@ -168,9 +179,15 @@ key_map($\^], none) -> auto_blink;
key_map($\^X, none) -> ctlx;
key_map($\^Y, none) -> yank;
key_map($\e, none) -> meta;
-key_map($), Prefix) when Prefix =/= meta -> {blink,$),$(};
-key_map($}, Prefix) when Prefix =/= meta -> {blink,$},${};
-key_map($], Prefix) when Prefix =/= meta -> {blink,$],$[};
+key_map($), Prefix) when Prefix =/= meta,
+ Prefix =/= search,
+ Prefix =/= search_meta -> {blink,$),$(};
+key_map($}, Prefix) when Prefix =/= meta,
+ Prefix =/= search,
+ Prefix =/= search_meta -> {blink,$},${};
+key_map($], Prefix) when Prefix =/= meta,
+ Prefix =/= search,
+ Prefix =/= search_meta -> {blink,$],$[};
key_map($B, meta) -> backward_word;
key_map($D, meta) -> kill_word;
key_map($F, meta) -> forward_word;
@@ -188,6 +205,32 @@ key_map($D, meta_left_sq_bracket) -> backward_char;
key_map($C, meta_left_sq_bracket) -> forward_char;
key_map(C, none) when C >= $\s ->
{insert,C};
+%% for search, we need smarter line handling and so
+%% we cheat a bit on the dispatching, and allow to
+%% return a mode.
+key_map($\^H, search) -> {search, backward_delete_char};
+key_map($\177, search) -> {search, backward_delete_char};
+key_map($\^R, search) -> {search, skip_up};
+key_map($\^S, search) -> {search, skip_down};
+key_map($\n, search) -> {search, search_found};
+key_map($\r, search) -> {search, search_found};
+key_map($\^A, search) -> {search, search_quit};
+key_map($\^B, search) -> {search, search_quit};
+key_map($\^D, search) -> {search, search_quit};
+key_map($\^E, search) -> {search, search_quit};
+key_map($\^F, search) -> {search, search_quit};
+key_map($\t, search) -> {search, search_quit};
+key_map($\^L, search) -> {search, search_quit};
+key_map($\^T, search) -> {search, search_quit};
+key_map($\^U, search) -> {search, search_quit};
+key_map($\^], search) -> {search, search_quit};
+key_map($\^X, search) -> {search, search_quit};
+key_map($\^Y, search) -> {search, search_quit};
+key_map($\e, search) -> search_meta;
+key_map($[, search_meta) -> search_meta_left_sq_bracket;
+key_map(_, search_meta) -> {search, search_quit};
+key_map(_C, search_meta_left_sq_bracket) -> {search, search_quit};
+key_map(C, search) -> {insert_search,C};
key_map(C, _) -> {undefined,C}.
%% do_op(Action, Before, After, Requests)
@@ -196,6 +239,57 @@ do_op({insert,C}, Bef, [], Rs) ->
{{[C|Bef],[]},[{put_chars, unicode,[C]}|Rs]};
do_op({insert,C}, Bef, Aft, Rs) ->
{{[C|Bef],Aft},[{insert_chars, unicode, [C]}|Rs]};
+%% Search mode prompt always looks like (search)`$TERMS': $RESULT.
+%% the {insert_search, _} handlings allow to share this implementation
+%% correctly with group.erl. This module provides $TERMS, and group.erl
+%% is in charge of providing $RESULT.
+%% This require a bit of trickery. Because search disables moving around
+%% on the line (left/right arrow keys and other shortcuts that just exit
+%% search mode), we can use the Bef and Aft variables to hold each
+%% part of the line. Bef takes charge of "(search)`$TERMS" and Aft
+%% takes charge of "': $RESULT".
+do_op({insert_search, C}, Bef, [], Rs) ->
+ Aft="': ",
+ {{[C|Bef],Aft},
+ [{insert_chars, unicode, [C]++Aft}, {delete_chars,-3} | Rs],
+ search};
+do_op({insert_search, C}, Bef, Aft, Rs) ->
+ Offset= length(Aft),
+ NAft = "': ",
+ {{[C|Bef],NAft},
+ [{insert_chars, unicode, [C]++NAft}, {delete_chars,-Offset} | Rs],
+ search};
+do_op({search, backward_delete_char}, [_|Bef], Aft, Rs) ->
+ Offset= length(Aft)+1,
+ NAft = "': ",
+ {{Bef,NAft},
+ [{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
+ search};
+do_op({search, backward_delete_char}, [], _Aft, Rs) ->
+ Aft="': ",
+ {{[],Aft}, Rs, search};
+do_op({search, skip_up}, Bef, Aft, Rs) ->
+ Offset= length(Aft),
+ NAft = "': ",
+ {{[$\^R|Bef],NAft}, % we insert ^R as a flag to whoever called us
+ [{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
+ search};
+do_op({search, skip_down}, Bef, Aft, Rs) ->
+ Offset= length(Aft),
+ NAft = "': ",
+ {{[$\^S|Bef],NAft}, % we insert ^S as a flag to whoever called us
+ [{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
+ search};
+do_op({search, search_found}, _Bef, Aft, Rs) ->
+ "': "++NAft = Aft,
+ {{[],NAft},
+ [{put_chars, unicode, "\n"}, {move_rel,-length(Aft)} | Rs],
+ search_found};
+do_op({search, search_quit}, _Bef, Aft, Rs) ->
+ "': "++NAft = Aft,
+ {{[],NAft},
+ [{put_chars, unicode, "\n"}, {move_rel,-length(Aft)} | Rs],
+ search_quit};
%% do blink after $$
do_op({blink,C,M}, Bef=[$$,$$|_], Aft, Rs) ->
N = over_paren(Bef, C, M),
@@ -453,6 +547,9 @@ prompt({line,Pbs,_,_}) ->
current_line({line,_,{Bef, Aft},_}) ->
reverse(Bef, Aft ++ "\n").
+current_chars({line,_,{Bef,Aft},_}) ->
+ reverse(Bef, Aft).
+
%% %% expand(CurrentBefore) ->
%% %% {yes,Expansion} | no
%% %% Try to expand the word before as either a module name or a function
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index a0f7660ecf..ebabf8d700 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1224,8 +1224,6 @@ macro_arg([{'try',Lr}|Toks], E, Arg) ->
macro_arg(Toks, ['end'|E], [{'try',Lr}|Arg]);
macro_arg([{'cond',Lr}|Toks], E, Arg) ->
macro_arg(Toks, ['end'|E], [{'cond',Lr}|Arg]);
-macro_arg([{'query',Lr}|Toks], E, Arg) ->
- macro_arg(Toks, ['end'|E], [{'query',Lr}|Arg]);
macro_arg([{Rb,Lrb}|Toks], [Rb|E], Arg) -> %Found matching close
macro_arg(Toks, E, [{Rb,Lrb}|Arg]);
macro_arg([T|Toks], E, Arg) ->
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 9a01e85006..642d972582 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2159,9 +2159,7 @@ expr({op,_Line,_Op,L,R}, Vt, St) ->
expr_list([L,R], Vt, St); %They see the same variables
%% The following are not allowed to occur anywhere!
expr({remote,Line,_M,_F}, _Vt, St) ->
- {[],add_error(Line, illegal_expr, St)};
-expr({'query',Line,_Q}, _Vt, St) ->
- {[],add_error(Line, {mnemosyne,"query"}, St)}.
+ {[],add_error(Line, illegal_expr, St)}.
%% expr_list(Expressions, Variables, State) ->
%% {UsedVarTable,State}
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 002abc11e8..8316462989 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -36,7 +36,7 @@ tuple
record_expr record_tuple record_field record_fields
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
fun_expr fun_clause fun_clauses atom_or_var integer_or_var
-try_expr try_catch try_clause try_clauses query_expr
+try_expr try_catch try_clause try_clauses
function_call argument_list
exprs guard
atomic strings
@@ -54,7 +54,7 @@ char integer float atom string var
'(' ')' ',' '->' ':-' '{' '}' '[' ']' '|' '||' '<-' ';' ':' '#' '.'
'after' 'begin' 'case' 'try' 'catch' 'end' 'fun' 'if' 'of' 'receive' 'when'
-'andalso' 'orelse' 'query'
+'andalso' 'orelse'
'bnot' 'not'
'*' '/' 'div' 'rem' 'band' 'and'
'+' '-' 'bor' 'bxor' 'bsl' 'bsr' 'or' 'xor'
@@ -272,7 +272,6 @@ expr_max -> case_expr : '$1'.
expr_max -> receive_expr : '$1'.
expr_max -> fun_expr : '$1'.
expr_max -> try_expr : '$1'.
-expr_max -> query_expr : '$1'.
list -> '[' ']' : {nil,?line('$1')}.
@@ -432,9 +431,6 @@ try_clause -> var ':' expr clause_guard clause_body :
L = ?line('$1'),
{clause,L,[{tuple,L,['$1','$3',{var,L,'_'}]}],'$4','$5'}.
-query_expr -> 'query' list_comprehension 'end' :
- {'query',?line('$1'),'$2'}.
-
argument_list -> '(' ')' : {[],?line('$1')}.
argument_list -> '(' exprs ')' : {'$2',?line('$1')}.
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 0383ce6839..0e1156075a 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -510,8 +510,6 @@ lexpr({'fun',_,{clauses,Cs}}, _Prec, Opts) ->
lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
{force_nl,fun_info(Extra),
{list,[{first,'fun',fun_clauses(Cs, Opts)},'end']}};
-lexpr({'query',_,Lc}, _Prec, Opts) ->
- {list,[{step,leaf("query"),lexpr(Lc, 0, Opts)},'end']};
lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
case erl_internal:bif(M, F, length(Args)) of
true ->
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index e5bb287c45..bc0eaf015d 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1404,7 +1404,6 @@ reserved_word('fun') -> true;
reserved_word('if') -> true;
reserved_word('let') -> true;
reserved_word('of') -> true;
-reserved_word('query') -> true;
reserved_word('receive') -> true;
reserved_word('when') -> true;
reserved_word('bnot') -> true;
diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl
index afe917b151..bc1bd06534 100644
--- a/lib/stdlib/src/queue.erl
+++ b/lib/stdlib/src/queue.erl
@@ -472,22 +472,24 @@ init(Q) -> drop_r(Q).
-compile({inline, [{r2f,1},{f2r,1}]}).
-%% Move all but two from R to F, if there are at least three
+%% Move half of elements from R to F, if there are at least three
r2f([]) ->
{[],[]};
r2f([_]=R) ->
{[],R};
r2f([X,Y]) ->
{[X],[Y]};
-r2f([X,Y|R]) ->
- {[X,Y],lists:reverse(R, [])}.
+r2f(List) ->
+ {FF,RR} = lists:split(length(List) div 2 + 1, List),
+ {FF,lists:reverse(RR, [])}.
-%% Move all but two from F to R, if there are enough
+%% Move half of elements from F to R, if there are enough
f2r([]) ->
{[],[]};
f2r([_]=F) ->
{F,[]};
f2r([X,Y]) ->
{[Y],[X]};
-f2r([X,Y|F]) ->
- {lists:reverse(F, []),[X,Y]}.
+f2r(List) ->
+ {FF,RR} = lists:split(length(List) div 2 + 1, List),
+ {lists:reverse(RR, []),FF}.
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index db416b03b0..37be61d665 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -537,29 +537,9 @@ messages(Config) when is_list(Config) ->
?line true = "\n" =:= lists:flatten(erl_pp:form({eof,0})),
ok.
-old_mnemosyne_syntax(suite) ->
- [];
old_mnemosyne_syntax(Config) when is_list(Config) ->
- %% Since we have kept the 'query' syntax and ':-' token,
+ %% Since we have kept the ':-' token,
%% better test that we can pretty print it.
- Q = {'query',6,
- {lc,6,
- {var,6,'X'},
- [{generate,6,
- {var,6,'X'},
- {call,6,{atom,6,table},[{atom,6,tab}]}},
- {match,7,
- {record_field,7,{var,7,'X'},{atom,7,foo}},
- {atom,7,bar}}]}},
- ?line "query\n"
- " [ \n" % extra space...
- " X ||\n"
- " X <- table(tab),\n"
- " X.foo = bar\n"
- " ]\n"
- "end" =
- lists:flatten(erl_pp:expr(Q)),
-
R = {rule,12,sales,2,
[{clause,12,
[{var,12,'E'},{atom,12,employee}],
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 34e1b99abe..9a6b2f8f34 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -197,7 +197,7 @@ otp_7810(Config) when is_list(Config) ->
reserved_words() ->
L = ['after', 'begin', 'case', 'try', 'cond', 'catch',
'andalso', 'orelse', 'end', 'fun', 'if', 'let', 'of',
- 'query', 'receive', 'when', 'bnot', 'not', 'div',
+ 'receive', 'when', 'bnot', 'not', 'div',
'rem', 'band', 'and', 'bor', 'bxor', 'bsl', 'bsr',
'or', 'xor'],
[begin
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 1a55a5e71c..1ffcf31134 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -813,13 +813,6 @@ lay_2(Node, Ctxt) ->
reset_prec(Ctxt)),
lay_parentheses(D, Ctxt);
- query_expr ->
- Ctxt1 = reset_prec(Ctxt),
- D = lay(erl_syntax:query_expr_body(Node), Ctxt1),
- sep([text("query"),
- nest(Ctxt1#ctxt.sub_indent, D),
- text("end")]);
-
receive_expr ->
Ctxt1 = reset_prec(Ctxt),
D1 = lay_clauses(erl_syntax:receive_expr_clauses(Node),
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index f7420030c3..41a1708925 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -235,8 +235,6 @@
prefix_expr/2,
prefix_expr_argument/1,
prefix_expr_operator/1,
- query_expr/1,
- query_expr_body/1,
receive_expr/1,
receive_expr/3,
receive_expr_action/1,
@@ -449,7 +447,6 @@
%% <td>parentheses</td>
%% <td>prefix_expr</td>
%% </tr><tr>
-%% <td>query_expr</td>
%% <td>receive_expr</td>
%% <td>record_access</td>
%% </tr><tr>
@@ -513,7 +510,6 @@
%% @see operator/1
%% @see parentheses/1
%% @see prefix_expr/2
-%% @see query_expr/1
%% @see receive_expr/3
%% @see record_access/3
%% @see record_expr/2
@@ -578,7 +574,6 @@ type(Node) ->
{match, _, _, _} -> match_expr;
{op, _, _, _, _} -> infix_expr;
{op, _, _, _} -> prefix_expr;
- {'query', _, _} -> query_expr;
{record, _, _, _, _} -> record_expr;
{record, _, _, _} -> record_expr;
{record_field, _, _, _, _} -> record_access;
@@ -4097,7 +4092,6 @@ record_access(Argument, Field) ->
%% @see record_access_type/1
%% @see record_access_field/1
%% @see record_expr/3
-%% @see query_expr/1
-record(record_access, {argument :: syntaxTree(),
type :: 'none' | syntaxTree(),
@@ -4574,50 +4568,6 @@ binary_comp_body(Node) ->
%% =====================================================================
-%% @doc Creates an abstract Mnemosyne query expression. The result
-%% represents "<code>query <em>Body</em> end</code>".
-%%
-%% @see query_expr_body/1
-%% @see record_access/2
-%% @see rule/2
-
-%% type(Node) = query_expr
-%% data(Node) = syntaxTree()
-%%
-%% `erl_parse' representation:
-%%
-%% {'query', Pos, Body}
-%%
-%% Body = erl_parse()
-
--spec query_expr(syntaxTree()) -> syntaxTree().
-
-query_expr(Body) ->
- tree(query_expr, Body).
-
-revert_query_expr(Node) ->
- Pos = get_pos(Node),
- Body = list_comp_body(Node),
- {'query', Pos, Body}.
-
-
-%% =====================================================================
-%% @doc Returns the body subtree of a `query_expr' node.
-%%
-%% @see query_expr/1
-
--spec query_expr_body(syntaxTree()) -> syntaxTree().
-
-query_expr_body(Node) ->
- case unwrap(Node) of
- {'query', _, Body} ->
- Body;
- Node1 ->
- data(Node1)
- end.
-
-
-%% =====================================================================
%% @doc Creates an abstract Mnemosyne rule. If `Clauses' is
%% `[C1, ..., Cn]', the results represents
%% "<code><em>Name</em> <em>C1</em>; ...; <em>Name</em>
@@ -6041,8 +5991,6 @@ revert_root(Node) ->
revert_parentheses(Node);
prefix_expr ->
revert_prefix_expr(Node);
- query_expr ->
- revert_query_expr(Node);
receive_expr ->
revert_receive_expr(Node);
record_access ->
@@ -6283,8 +6231,6 @@ subtrees(T) ->
prefix_expr ->
[[prefix_expr_operator(T)],
[prefix_expr_argument(T)]];
- query_expr ->
- [[query_expr_body(T)]];
receive_expr ->
case receive_expr_timeout(T) of
none ->
@@ -6413,7 +6359,6 @@ make_tree(match_expr, [[P], [E]]) -> match_expr(P, E);
make_tree(module_qualifier, [[M], [N]]) -> module_qualifier(M, N);
make_tree(parentheses, [[E]]) -> parentheses(E);
make_tree(prefix_expr, [[F], [A]]) -> prefix_expr(F, A);
-make_tree(query_expr, [[B]]) -> query_expr(B);
make_tree(receive_expr, [C]) -> receive_expr(C);
make_tree(receive_expr, [C, [E], A]) -> receive_expr(C, E, A);
make_tree(record_access, [[E], [F]]) ->
diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl
index d9a699ca9f..c0200ab67c 100644
--- a/lib/test_server/src/ts_lib.erl
+++ b/lib/test_server/src/ts_lib.erl
@@ -143,7 +143,6 @@ suite_order(inets) -> 28;
suite_order(asn1) -> 30;
suite_order(os_mon) -> 32;
suite_order(snmp) -> 38;
-suite_order(mnemosyne) -> 40;
suite_order(mnesia_session) -> 42;
suite_order(mnesia) -> 44;
suite_order(system) -> 999; %% IMPORTANT: system SHOULD always be last!
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index ab29d156aa..680c1781ca 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1519,12 +1519,6 @@ aux_var(Vars, N) ->
%% This way we will be able to exclude functions defined in include files.
munge({function,0,module_info,_Arity,_Clauses},_Vars,_MainFile,_Switch) ->
ignore; % module_info will be added again when the forms are recompiled
-munge(Form={function,_,'MNEMOSYNE QUERY',_,_},Vars,_MainFile,Switch) ->
- {Form,Vars,Switch}; % No bumps in Mnemosyne code.
-munge(Form={function,_,'MNEMOSYNE RULE',_,_},Vars,_MainFile,Switch) ->
- {Form,Vars,Switch};
-munge(Form={function,_,'MNEMOSYNE RECFUNDEF',_,_},Vars,_MainFile,Switch) ->
- {Form,Vars,Switch};
munge({function,Line,Function,Arity,Clauses},Vars,_MainFile,on) ->
Vars2 = Vars#vars{function=Function,
arity=Arity,
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index 92f0c45c7b..2fcc2c503c 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -80,12 +80,6 @@ form({attribute, Line, xref, Calls}, S) -> % experimental
attr(Calls, Line, M, Fun, L, X, B, S);
form({attribute, _Line, _Attr, _Val}, S) ->
S;
-form({function, 0, 'MNEMOSYNE RULE', 1, _Clauses}, S) ->
- S;
-form({function, 0, 'MNEMOSYNE QUERY', 2, _Clauses}, S) ->
- S;
-form({function, 0, 'MNEMOSYNE RECFUNDEF', 1, _Clauses}, S) ->
- S;
form({function, 0, module_info, 0, _Clauses}, S) ->
S;
form({function, 0, module_info, 1, _Clauses}, S) ->
@@ -331,9 +325,6 @@ handle_call(Locality, Module, Name, Arity, Line, S) ->
handle_call(Locality, To, Line, S, false)
end.
-handle_call(_Locality, {_, 'MNEMOSYNE RULE',1}, _Line, S, _) -> S;
-handle_call(_Locality, {_, 'MNEMOSYNE QUERY', 2}, _Line, S, _) -> S;
-handle_call(_Locality, {_, 'MNEMOSYNE RECFUNDEF',1}, _Line, S, _) -> S;
handle_call(Locality, To0, Line, S, IsUnres) ->
From = S#xrefr.function,
To = adjust_arity(S, To0),
diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl
index 93caee0c8f..ce5cf66a14 100644
--- a/lib/tools/test/cprof_SUITE.erl
+++ b/lib/tools/test/cprof_SUITE.erl
@@ -230,10 +230,10 @@ on_load_test(Config) ->
%%
?line N4 = cprof:restart(),
?line {ok,Module} = c:c(File, [{outdir,Priv}]),
- ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
- ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
- ?line L = seq(1, M, fun (I) -> succ(I) end),
- ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = Module:seq(1, M, fun succ/1),
+ ?line Lr = Module:seq_r(1, M, fun succ/1),
+ ?line L = seq(1, M, fun succ/1),
+ ?line Lr = seq_r(1, M, fun succ/1),
?line N2 = cprof:pause(),
?line {Module,0,[]} = cprof:analyse(Module),
?line M_1 = M - 1,
@@ -265,10 +265,10 @@ modules_test(Config) ->
?line M2__1 = M2 + 1,
?line erlang:yield(),
?line N = cprof:start(),
- ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
- ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
- ?line L = seq(1, M, fun (I) -> succ(I) end),
- ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = Module:seq(1, M, fun succ/1),
+ ?line Lr = Module:seq_r(1, M, fun succ/1),
+ ?line L = seq(1, M, fun succ/1),
+ ?line Lr = seq_r(1, M, fun succ/1),
?line N = cprof:pause(),
?line Lr = lists:reverse(L),
?line M_1 = M - 1,
diff --git a/lib/tv/src/tv_main.hrl b/lib/tv/src/tv_main.hrl
index 28329ca83c..06b405ac1f 100644
--- a/lib/tv/src/tv_main.hrl
+++ b/lib/tv/src/tv_main.hrl
@@ -131,7 +131,6 @@
ir_WstringDef,
lmcounter,
locks,
- mnemosyne_tmp,
pg2_table,
queue,
snmp_agent_table,
diff --git a/lib/wx/examples/demo/demo_html_tagger.erl b/lib/wx/examples/demo/demo_html_tagger.erl
index 243e5d659f..46bfe73676 100644
--- a/lib/wx/examples/demo/demo_html_tagger.erl
+++ b/lib/wx/examples/demo/demo_html_tagger.erl
@@ -485,7 +485,6 @@ is_keyword('not') -> true;
is_keyword('of' ) -> true;
is_keyword('or' ) -> true;
is_keyword('orelse' ) -> true;
-is_keyword('query' ) -> true;
is_keyword('receive' ) -> true;
is_keyword('rem' ) -> true;
is_keyword('spec') -> true;
diff --git a/make/fakefop b/make/fakefop
index bbe81ef3b1..b64428bbd1 100755
--- a/make/fakefop
+++ b/make/fakefop
@@ -1,10 +1,9 @@
#!/bin/sh
#
-# Copyright Tuncer Ayaz 2010. All Rights Reserved.
-#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Tuncer Ayaz 2010-2013. All Rights Reserved.
+# Copyright Ericsson AB 2010-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -22,92 +21,85 @@
# Author: Tuncer Ayaz
#
-if [ $# -lt 4 ]
+if [ $# -lt 6 ]
then
- echo "Usage: fakefop -fo IGNORED -pdf OUTFILE"
+ echo "Usage: fakefop -c IGNORED -fo IGNORED -pdf OUTFILE"
exit 1
fi
-OUTFILE=$4
-NAME=`basename $4 .pdf`
+OUTFILE=$6
+
+echo -n -e '%PDF-1.4\n%\0342\0343\0317\0323\n\n' > $OUTFILE
-echo Write $OUTFILE
-cat > $OUTFILE <<EndOfFile
-%PDF-1.4
+cat >> $OUTFILE <<EndOfFile
1 0 obj
- << /Type /Catalog
- /Outlines 2 0 R
- /Pages 3 0 R
- >>
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
endobj
2 0 obj
- << /Type /Outlines
- /Count 0
- >>
+<<
+ /Type /Pages
+ /Kids [ 3 0 R ]
+ /Count 1
+>>
endobj
3 0 obj
- << /Type /Pages
- /Kids [4 0 R]
- /Count 1
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [ 0 0 612 492 ]
+ /Contents 5 0 R
+ /Resources <<
+ /Font <<
+ /F1 4 0 R
+ >>
>>
+>>
endobj
4 0 obj
- << /Type /Page
- /Parent 3 0 R
- /MediaBox [0 0 612 492]
- /Contents 5 0 R
- /Resources << /ProcSet 6 0 R
- /Font << /F1 7 0 R >>
- >>
- >>
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /StandardEncoding
+>>
endobj
5 0 obj
- << /Length 73 >>
+<<
+ /Length 74
+>>
stream
- BT
- /F1 24 Tf
- 10 400 Td
- ($NAME) Tj
- ET
- BT
- /F1 24 Tf
- 10 350 Td
- (\(placeholder PDF generated without FOP\)) Tj
- ET
+BT
+/F1 24 Tf
+10 400 Td
+(\(placeholder PDF generated with fakefop\)) Tj
+ET
endstream
endobj
-6 0 obj
- [/PDF /Text]
-endobj
-7 0 obj
- << /Type /Font
- /Subtype /Type1
- /Name /F1
- /BaseFont /Helvetica
- /Encoding /MacRomanEncoding
- >>
-endobj
xref
-0 8
-0000000000 65535 f
-0000000009 00000 n
-0000000074 00000 n
-0000000120 00000 n
-0000000179 00000 n
-0000000364 00000 n
-0000000466 00000 n
-0000000496 00000 n
+0 6
+0000000000 65536 f
+0000000016 00000 n
+0000000070 00000 n
+0000000136 00000 n
+0000000291 00000 n
+0000000410 00000 n
trailer
- << /Size 8
- /Root 1 0 R
- >>
+<<
+ /Size 6
+ /Root 1 0 R
+>>
+
startxref
-625
+536
%%EOF
EndOfFile
diff --git a/make/otp.mk.in b/make/otp.mk.in
index 0e58a27016..fca9cf3cff 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -255,6 +255,7 @@ DEFAULT_GIF_FILES = $(HTMLDIR)/min_head.gif
#
XSLTPROC = @XSLTPROC@
FOP = @FOP@
+XMLLINT = @XMLLINT@
DOCGEN=$(ERL_TOP)/lib/erl_docgen
FOP_CONFIG = $(DOCGEN)/priv/fop.xconf
diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk
index 0be0a2de56..65a2e62979 100644
--- a/make/otp_release_targets.mk
+++ b/make/otp_release_targets.mk
@@ -106,6 +106,9 @@ $(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES)
docs: $(HTMLDIR)/$(APPLICATION).eix
+xmllint: $(XML_FILES)
+ $(XMLLINT) --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities $(XML_FILES)
+
# ----------------------------------------------------
# Local documentation target for testing
# ----------------------------------------------------