diff options
author | Maxim Fedorov <maximfca@gmail.com> | 2021-05-22 22:32:36 -0700 |
---|---|---|
committer | Sverker Eriksson <sverker@erlang.org> | 2021-05-25 11:48:27 +0200 |
commit | ddbb46df7afb5d27d4db40bed33e900e18f2e350 (patch) | |
tree | 5026892d9ca278d54b4d084fc68dd694080a7c1f | |
parent | 2bcd9dca08421c6f961223cebf7b781aaf387a23 (diff) | |
download | erlang-ddbb46df7afb5d27d4db40bed33e900e18f2e350.tar.gz |
erts: Fix internal hash for external pids/ports
When 64-bit external pid and ports were introduced in OTP-24.0,
internal hash function was not adjusted accordingly. This led to a large
amount of hash collisions, ultimately making maps:from_list and
maps:from_keys to crash the emulator (stack overflow, or assertion
in a debug build).
Co-authored-by: Sverker Eriksson <sverker@erlang.org>
-rw-r--r-- | erts/emulator/beam/utils.c | 12 | ||||
-rw-r--r-- | erts/emulator/test/map_SUITE.erl | 13 | ||||
-rw-r--r-- | erts/etc/unix/etp-commands.in | 12 |
3 files changed, 23 insertions, 14 deletions
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 7df04420da..9947386efa 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -2343,23 +2343,15 @@ make_internal_hash(Eterm term, Uint32 salt) case EXTERNAL_PID_SUBTAG: { ExternalThing* thing = external_thing_ptr(term); /* See limitation #2 */ - #ifdef ARCH_64 POINTER_HASH(thing->node, HCONST_5); - UINT32_HASH(thing->data.ui[0], HCONST_5); - #else - UINT32_HASH_2(thing->node, thing->data.ui[0], HCONST_5); - #endif + UINT32_HASH_2(thing->data.pid.num, thing->data.pid.ser, HCONST_5); goto pop_next; } case EXTERNAL_PORT_SUBTAG: { ExternalThing* thing = external_thing_ptr(term); /* See limitation #2 */ - #ifdef ARCH_64 POINTER_HASH(thing->node, HCONST_6); - UINT32_HASH(thing->data.ui[0], HCONST_6); - #else - UINT32_HASH_2(thing->node, thing->data.ui[0], HCONST_6); - #endif + UINT32_HASH_2(thing->data.ui32[0], thing->data.ui32[1], HCONST_6); goto pop_next; } case FLOAT_SUBTAG: diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl index 7ace75cab4..c6302d0239 100644 --- a/erts/emulator/test/map_SUITE.erl +++ b/erts/emulator/test/map_SUITE.erl @@ -2966,6 +2966,19 @@ t_erts_internal_hash(_Config) when is_list(_Config) -> i = maps:get({[0,0,0,0,0,0,0]},M7), j = maps:get({[0,0,0,0,0,0,0,0]},M7), k = maps:get({[0,0,0,0,0,0,0,0,0]},M7), + + %% Test that external pids and ports don't introduce hash clash, + %% caused by high word being ignored (OTP-17436). + maps:from_keys([erts_test_utils:mk_ext_pid({a@a, 17}, + 1 bsl NumBit, + 1 bsl SerBit) + || NumBit <- lists:seq(0, 31), + SerBit <- lists:seq(0, 31)], + 1), + maps:from_keys([erts_test_utils:mk_ext_port({a@a, 17}, 1 bsl NumBit) + || NumBit <- lists:seq(0, 63)], + 1), + ok. t_pdict(_Config) -> diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in index ba35ee7091..620ad2679e 100644 --- a/erts/etc/unix/etp-commands.in +++ b/erts/etc/unix/etp-commands.in @@ -866,8 +866,8 @@ define etp-extpid-1 printf "#NotExternalPid<%p>", $etp_extpid_1_p->header else ## External pid - set $etp_extpid_1_number = $etp_extpid_1_p->data.ui[0]&0x7fff - set $etp_extpid_1_serial = ($etp_extpid_1_p->data.ui[0]>>15)&0x1fff + set $etp_extpid_1_number = $etp_extpid_1_p->data.ui32[0] + set $etp_extpid_1_serial = $etp_extpid_1_p->data.ui32[1] set $etp_extpid_1_np = $etp_extpid_1_p->node set $etp_extpid_1_creation = $etp_extpid_1_np->creation set $etp_extpid_1_dep = $etp_extpid_1_np->dist_entry @@ -926,7 +926,11 @@ define etp-extport-1 printf "#NotExternalPort<%p>", $etp_extport_1->header else ## External port - set $etp_extport_1_number = $etp_extport_1_p->data.ui[0]&0x3ffff + if $etp_arch64 + set $etp_extport_1_number = $etp_extport_1_p->data.port.id + else + set $etp_extport_1_number = $etp_extport_1_p->data.port.low | (((Uint64)$etp_extport_1_p->data.port.high) << 32) + end set $etp_extport_1_np = $etp_extport_1_p->node set $etp_extport_1_creation = $etp_extport_1_np->creation set $etp_extport_1_dep = $etp_extport_1_np->dist_entry @@ -941,7 +945,7 @@ define etp-extport-1 printf "#Port<%u:", $etp_extport_1_node>>6 end etp-atom-1 ($etp_extport_1_node) - printf "/%u.%u>", $etp_extport_1_creation, $etp_extport_1_number + printf "/%u.%lu>", $etp_extport_1_creation, $etp_extport_1_number end end end |