summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_bif_info.c15
-rw-r--r--erts/emulator/beam/erl_db_util.c12
-rw-r--r--erts/emulator/beam/erl_db_util.h30
-rw-r--r--erts/emulator/beam/erl_node_tables.c2
-rw-r--r--erts/emulator/test/socket_SUITE.erl28
-rw-r--r--erts/etc/common/erlc.c13
6 files changed, 73 insertions, 27 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 7db8142d28..b06b5fc1ab 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -164,20 +164,21 @@ static Eterm current_stacktrace(ErtsHeapFactory *hfact, Process* rp,
Eterm
erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail)
{
- struct erl_off_heap_header* ohh;
+ union erl_off_heap_ptr u;
Eterm res = tail;
Eterm tuple;
+ struct erts_tmp_aligned_offheap tmp;
- for (ohh = oh->first; ohh; ohh = ohh->next) {
- if (ohh->thing_word == HEADER_PROC_BIN) {
- ProcBin* pb = (ProcBin*) ohh;
- Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val);
- Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size);
+ for (u.hdr = oh->first; u.hdr; u.hdr = u.hdr->next) {
+ erts_align_offheap(&u, &tmp);
+ if (u.hdr->thing_word == HEADER_PROC_BIN) {
+ Eterm val = erts_bld_uword(hpp, szp, (UWord) u.pb->val);
+ Eterm orig_size = erts_bld_uint(hpp, szp, u.pb->val->orig_size);
if (szp)
*szp += 4+2;
if (hpp) {
- Uint refc = (Uint) erts_refc_read(&pb->val->intern.refc, 1);
+ Uint refc = (Uint) erts_refc_read(&u.pb->val->intern.refc, 1);
tuple = TUPLE3(*hpp, val, orig_size, make_small(refc));
res = CONS(*hpp + 4, tuple, res);
*hpp += 4+2;
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 1ea7074d21..ed09a34ae4 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -3285,22 +3285,15 @@ Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p,
void db_cleanup_offheap_comp(DbTerm* obj)
{
union erl_off_heap_ptr u;
- ProcBin tmp;
+ struct erts_tmp_aligned_offheap tmp;
for (u.hdr = obj->first_oh; u.hdr; u.hdr = u.hdr->next) {
- if ((UWord)u.voidp % sizeof(Uint) != 0) { /* unaligned ptr */
- sys_memcpy(&tmp, u.voidp, sizeof(tmp));
- /* Warning, must pass (void*)-variable to memcpy. Otherwise it will
- cause Bus error on Sparc due to false compile time assumptions
- about word aligned memory (type cast is not enough) */
- u.pb = &tmp;
- }
+ erts_align_offheap(&u, &tmp);
switch (thing_subtag(u.hdr->thing_word)) {
case REFC_BINARY_SUBTAG:
erts_bin_release(u.pb->val);
break;
case FUN_SUBTAG:
- ASSERT(u.pb != &tmp);
if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) {
erts_erase_fun_entry(u.fun->fe);
}
@@ -3311,7 +3304,6 @@ void db_cleanup_offheap_comp(DbTerm* obj)
break;
default:
ASSERT(is_external_header(u.hdr->thing_word));
- ASSERT(u.pb != &tmp);
erts_deref_node_entry(u.ext->node, make_boxed(u.ep));
break;
}
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 7a21de9a6c..f038dba89a 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -543,6 +543,17 @@ ERTS_GLB_INLINE Eterm erts_db_make_match_prog_ref(Process *p, Binary *mp, Eterm
ERTS_GLB_INLINE Binary *erts_db_get_match_prog_binary(Eterm term);
ERTS_GLB_INLINE Binary *erts_db_get_match_prog_binary_unchecked(Eterm term);
+/* @brief Ensure off-heap header is word aligned, make a temporary copy if not.
+ * Needed when inspecting ETS off-heap lists that may contain unaligned
+ * ProcBins if table is 'compressed'.
+ */
+struct erts_tmp_aligned_offheap
+{
+ ProcBin proc_bin;
+};
+ERTS_GLB_INLINE void erts_align_offheap(union erl_off_heap_ptr*,
+ struct erts_tmp_aligned_offheap* tmp);
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
/*
@@ -575,6 +586,25 @@ erts_db_get_match_prog_binary(Eterm term)
return bp;
}
+ERTS_GLB_INLINE void
+erts_align_offheap(union erl_off_heap_ptr* ohp,
+ struct erts_tmp_aligned_offheap* tmp)
+{
+ if ((UWord)ohp->voidp % sizeof(UWord) != 0) {
+ /*
+ * ETS store word unaligned ProcBins in its compressed format.
+ * Make a temporary aligned copy.
+ *
+ * Warning, must pass (void*)-variable to memcpy. Otherwise it will
+ * cause Bus error on Sparc due to false compile time assumptions
+ * about word aligned memory (type cast is not enough).
+ */
+ sys_memcpy(tmp, ohp->voidp, sizeof(*tmp));
+ ASSERT(tmp->proc_bin.thing_word == HEADER_PROC_BIN);
+ ohp->pb = &tmp->proc_bin;
+ }
+}
+
#endif
/*
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 50e9812534..8863e219e2 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1509,10 +1509,12 @@ static void
insert_offheap(ErlOffHeap *oh, int type, Eterm id)
{
union erl_off_heap_ptr u;
+ struct erts_tmp_aligned_offheap tmp;
struct insert_offheap2_arg a;
a.type = BIN_REF;
for (u.hdr = oh->first; u.hdr; u.hdr = u.hdr->next) {
+ erts_align_offheap(&u, &tmp);
switch (thing_subtag(u.hdr->thing_word)) {
case REF_SUBTAG:
if (ErtsIsDistEntryBinary(u.mref->mb))
diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl
index 4980ea2a82..124ae09951 100644
--- a/erts/emulator/test/socket_SUITE.erl
+++ b/erts/emulator/test/socket_SUITE.erl
@@ -1776,7 +1776,7 @@ quiet_mode(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% A simple test case that tests that the global debug can be channged.
+%% A simple test case that tests that the global debug can be changed.
%% At the same time, it will test the info function (since it uses it
%% for verification).
@@ -1794,7 +1794,8 @@ api_m_debug(_Config) when is_list(_Config) ->
%% For some reason this test case triggers a gcc bug, which causes
%% a segfault, on an ancient Fedora 16 VM. So, check the version of gcc...
-%% Not pretty, but the simplest way to skip (without actually testing for the host).
+%% Not pretty, but the simplest way to skip (without actually testing
+%% for the host).
has_bugfree_gcc() ->
has_bugfree_gcc(os:type()).
@@ -19470,6 +19471,7 @@ traffic_ping_pong_large_send_and_recv_tcp4(_Config) when is_list(_Config) ->
Msg = l2b(?TPP_LARGE),
Num = ?TPP_LARGE_NUM,
tc_try(traffic_ping_pong_large_send_and_recv_tcp4,
+ fun() -> is_old_fedora16() end,
fun() ->
InitState = #{domain => inet,
proto => tcp,
@@ -19496,7 +19498,8 @@ traffic_ping_pong_large_send_and_recv_tcp6(_Config) when is_list(_Config) ->
Msg = l2b(?TPP_LARGE),
Num = ?TPP_LARGE_NUM,
tc_try(traffic_ping_pong_large_send_and_recv_tcp6,
- fun() -> has_support_ipv6() end,
+ fun() -> is_old_fedora16(),
+ has_support_ipv6() end,
fun() ->
?TT(?SECS(45)),
InitState = #{domain => inet6,
@@ -19545,9 +19548,28 @@ traffic_ping_pong_large_host_cond() ->
traffic_ping_pong_large_host_cond({unix, sunos}, _) ->
skip("TC does not work on platform");
+traffic_ping_pong_large_host_cond({unix, linux}, _) ->
+ traffic_ping_pong_large_host_cond2(string:trim(os:cmd("cat /etc/issue")));
traffic_ping_pong_large_host_cond(_, _) ->
ok.
+traffic_ping_pong_large_host_cond2("Welcome to SUSE Linux Enterprise Server 10 SP1 (i586)" ++ _) ->
+ skip("TC does not work on platform");
+traffic_ping_pong_large_host_cond2("Fedora release 16 " ++ _) ->
+ skip("Very slow VM");
+traffic_ping_pong_large_host_cond2(_) ->
+ ok.
+
+
+is_old_fedora16() ->
+ is_old_fedora16(string:trim(os:cmd("cat /etc/issue"))).
+
+%% We actually only have one host running this, a slow VM.
+is_old_fedora16("Fedora release 16 " ++ _) ->
+ skip("Very slow VM");
+is_old_fedora16(_) ->
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index a9ee023727..56060497f3 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -233,10 +233,6 @@ int main(int argc, char** argv)
if (strlen(emulator) >= MAXPATHLEN)
error("Value of environment variable ERLC_EMULATOR is too large");
-#ifndef __WIN32__
- emulator = find_executable(emulator);
-#endif
-
/*
* Add scriptname to env
*/
@@ -256,7 +252,10 @@ int main(int argc, char** argv)
#ifdef __WIN32__
set_env("ERLC_CONFIGURATION", get_env("PATH"));
#else
- set_env("ERLC_CONFIGURATION", emulator);
+ {
+ char* full_path_emulator = find_executable(emulator);
+ set_env("ERLC_CONFIGURATION", full_path_emulator);
+ }
#endif
/*
@@ -595,7 +594,7 @@ run_erlang(char* progname, char** argv)
}
return status;
#else
- execv(progname, argv);
+ execvp(progname, argv);
error("Error %d executing \'%s\'.", errno, progname);
return 2;
#endif
@@ -949,7 +948,7 @@ start_compile_server(char* node_name, char** argv)
}
#else
if (fork() == 0) {
- execv(eargv[0], eargv);
+ execvp(eargv[0], eargv);
error("Error %d executing \'%s\'.", errno, progname);
}
#endif