aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/configure.in5
-rw-r--r--erts/doc/src/erl.xml31
-rw-r--r--erts/emulator/beam/atom.names1
-rw-r--r--erts/emulator/beam/beam_bif_load.c44
-rw-r--r--erts/emulator/beam/beam_bp.c10
-rw-r--r--erts/emulator/beam/beam_load.c16
-rw-r--r--erts/emulator/beam/bif.c2
-rw-r--r--erts/emulator/beam/break.c39
-rw-r--r--erts/emulator/beam/code_ix.c46
-rw-r--r--erts/emulator/beam/code_ix.h2
-rw-r--r--erts/emulator/beam/erl_alloc.c6
-rw-r--r--erts/emulator/beam/erl_bif_os.c2
-rw-r--r--erts/emulator/beam/erl_bif_trace.c42
-rw-r--r--erts/emulator/beam/erl_db_util.c10
-rw-r--r--erts/emulator/beam/erl_lock_check.c2
-rw-r--r--erts/emulator/beam/erl_message.c1
-rw-r--r--erts/emulator/beam/erl_mtrace.c2
-rw-r--r--erts/emulator/beam/erl_posix_str.c1
-rw-r--r--erts/emulator/beam/erl_process.c105
-rw-r--r--erts/emulator/beam/erl_process.h12
-rw-r--r--erts/emulator/beam/erl_process_dump.c2
-rw-r--r--erts/emulator/beam/erl_process_lock.c2
-rw-r--r--erts/emulator/beam/erl_resolv_dns.c23
-rw-r--r--erts/emulator/beam/erl_resolv_nodns.c23
-rw-r--r--erts/emulator/beam/erl_term.c2
-rw-r--r--erts/emulator/beam/external.c4
-rwxr-xr-xerts/emulator/beam/global.h3
-rw-r--r--erts/emulator/beam/index.c3
-rw-r--r--erts/emulator/beam/io.c26
-rw-r--r--erts/emulator/beam/module.c2
-rw-r--r--erts/emulator/beam/sys.h6
-rw-r--r--erts/emulator/drivers/common/inet_drv.c1
-rw-r--r--erts/emulator/drivers/win32/registry_drv.c2
-rw-r--r--erts/emulator/sys/unix/sys.c108
-rw-r--r--erts/emulator/sys/unix/sys_float.c8
-rwxr-xr-xerts/emulator/sys/win32/sys.c103
-rw-r--r--erts/emulator/sys/win32/sys_float.c8
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.c10
-rw-r--r--erts/emulator/test/binary_SUITE.erl26
-rw-r--r--erts/emulator/test/save_calls_SUITE.erl27
-rw-r--r--erts/emulator/test/smoke_test_SUITE.erl35
-rwxr-xr-xerts/emulator/utils/beam_makeops21
-rw-r--r--erts/epmd/src/epmd.c2
-rw-r--r--erts/epmd/src/epmd_srv.c7
-rw-r--r--erts/etc/common/erlexec.c3
-rw-r--r--erts/etc/common/heart.c214
-rw-r--r--erts/etc/common/inet_gethost.c12
-rw-r--r--erts/etc/unix/cerl.src15
-rw-r--r--erts/etc/win32/nsis/Makefile2
-rw-r--r--erts/include/internal/ethread.h2
-rw-r--r--erts/test/otp_SUITE.erl21
51 files changed, 698 insertions, 404 deletions
diff --git a/erts/configure.in b/erts/configure.in
index 43f6cf39c9..3256b0cb59 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -3579,6 +3579,11 @@ case $host_os in
DED_LDFLAGS="-m32 $DED_LDFLAGS"
fi
;;
+ openbsd*)
+ DED_LD="$CC"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
+ DED_LDFLAGS="-shared"
+ ;;
osf*)
# NOTE! Whitespace after -rpath is important.
DED_LD_FLAG_RUNTIME_LIBRARY_PATH="-rpath "
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 93d1289e8d..7cdb3a4dfe 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -1042,6 +1042,37 @@
the emulator will be allowed to spend writing a crash dump. When
the given number of seconds have elapsed, the emulator will be
terminated by a SIGALRM signal.</p>
+
+ <p> If the environment variable is <em>not</em> set or it is set to zero seconds, <c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c>,
+ the runtime system will not even attempt to write the crash dump file. It will just terminate.
+ </p>
+ <p> If the environment variable is set to negative valie, e.g. <c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c>,
+ the runtime system will wait indefinitely for the crash dump file to be written.
+ </p>
+ <p> This environment variable is used in conjuction with
+ <seealso marker="kernel:heart"><c>heart</c></seealso> if <c>heart</c> is running:
+ </p>
+ <taglist>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag>
+ <item><p>
+ Suppresses the writing a crash dump file entirely,
+ thus rebooting the runtime system immediately.
+ This is the same as not setting the environment variable.
+ </p>
+ </item>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag>
+ <item><p>Setting the environment variable to a negative value will cause the
+ termination of the runtime system to wait until the crash dump file
+ has been completly written.
+ </p>
+ </item>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag>
+ <item><p>
+ Will wait for <c>S</c> seconds to complete the crash dump file and
+ then terminate the runtime system.
+ </p>
+ </item>
+ </taglist>
</item>
<tag><c><![CDATA[ERL_AFLAGS]]></c></tag>
<item>
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 106fad030b..afcbd732df 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -252,6 +252,7 @@ atom heap_block_size
atom heap_size
atom heap_sizes
atom heap_type
+atom heart_port
atom heir
atom hidden
atom hide
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index e8f8a04344..9e4add823d 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -148,6 +148,15 @@ struct m {
};
static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int);
+#ifdef ERTS_SMP
+static void smp_code_ix_commiter(void*);
+
+static struct /* Protected by code_write_permission */
+{
+ Process* stager;
+ ErtsThrPrgrLaterOp lop;
+}commiter_state;
+#endif
static Eterm
exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions)
@@ -347,7 +356,6 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
}
#ifdef ERTS_SMP
else {
- ErtsThrPrgrVal later;
ASSERT(is_value(res));
if (loaded) {
@@ -356,17 +364,17 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
erts_end_staging_code_ix();
/*
* Now we must wait for all schedulers to do a memory barrier before
- * we can activate and let them access the new staged code. This allows
+ * we can commit and let them access the new staged code. This allows
* schedulers to read active code_ix in a safe way while executing
* without any memory barriers at all.
*/
-
- later = erts_thr_progress_later(c_p->scheduler_data);
- erts_thr_progress_wakeup(c_p->scheduler_data, later);
- erts_notify_code_ix_activation(c_p, later);
+ ASSERT(commiter_state.stager == NULL);
+ commiter_state.stager = c_p;
+ erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &commiter_state.lop);
+ erts_smp_proc_inc_refc(c_p);
erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
/*
- * handle_code_ix_activation() will do the rest "later"
+ * smp_code_ix_commiter() will do the rest "later"
* and resume this process to return 'res'.
*/
ERTS_BIF_YIELD_RETURN(c_p, res);
@@ -374,6 +382,28 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
#endif
}
+
+#ifdef ERTS_SMP
+static void smp_code_ix_commiter(void* null)
+{
+ Process* p = commiter_state.stager;
+
+ erts_commit_staging_code_ix();
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ }
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ erts_smp_proc_dec_refc(p);
+#ifdef DEBUG
+ commiter_state.stager = NULL;
+#endif
+ erts_release_code_write_permission();
+}
+#endif /* ERTS_SMP */
+
+
+
BIF_RETTYPE
check_old_code_1(BIF_ALIST_1)
{
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 50d18b0347..58e0090a76 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -254,7 +254,7 @@ erts_consolidate_bp_data(BpFunctions* f, int local)
Uint i;
Uint n = f->matched;
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
for (i = 0; i < n; i++) {
consolidate_bp_data(fs[i].mod, fs[i].pc, local);
@@ -266,7 +266,7 @@ erts_consolidate_bif_bp_data(void)
{
int i;
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
for (i = 0; i < BIF_SIZE; i++) {
Export *ep = bif_export[i];
consolidate_bp_data(0, ep->code+3, 0);
@@ -692,7 +692,7 @@ erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I)
* export entry */
BeamInstr *cp = p->cp;
GenericBp* g;
- GenericBpData* bp;
+ GenericBpData* bp = NULL;
Uint bp_flags = 0;
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
@@ -1449,7 +1449,7 @@ set_function_break(BeamInstr *pc, Binary *match_spec, Uint break_flags,
Uint common;
ErtsBpIndex ix = erts_staging_bp_ix();
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
g = (GenericBp *) pc[-4];
if (g == 0) {
int i;
@@ -1565,7 +1565,7 @@ clear_function_break(BeamInstr *pc, Uint break_flags)
Uint common;
ErtsBpIndex ix = erts_staging_bp_ix();
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
if ((g = (GenericBp *) pc[-4]) == 0) {
return 1;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index d3f55a2ba4..b51f076a5d 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -756,7 +756,7 @@ erts_finish_loading(Binary* magic, Process* c_p,
* table which is not protected by any locks.
*/
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_is_code_ix_locked() ||
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_has_code_write_permission() ||
erts_smp_thr_progress_is_blocking());
/*
@@ -5527,7 +5527,8 @@ stub_copy_info(LoaderState* stp,
int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */
byte* info, /* Where to store info. */
BeamInstr* ptr_word, /* Where to store pointer into info. */
- BeamInstr* size_word) /* Where to store size of info. */
+ BeamInstr* size_word, /* Where to store size into info. */
+ BeamInstr* size_on_heap_word) /* Where to store size on heap. */
{
Sint decoded_size;
Uint size = stp->chunks[chunk].size;
@@ -5538,7 +5539,8 @@ stub_copy_info(LoaderState* stp,
if (decoded_size < 0) {
return 0;
}
- *size_word = decoded_size;
+ *size_word = (BeamInstr) size;
+ *size_on_heap_word = decoded_size;
}
return info + size;
}
@@ -5960,12 +5962,16 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
info = (byte *) fp;
info = stub_copy_info(stp, ATTR_CHUNK, info,
- code+MI_ATTR_PTR, code+MI_ATTR_SIZE_ON_HEAP);
+ code+MI_ATTR_PTR,
+ code+MI_ATTR_SIZE,
+ code+MI_ATTR_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
}
info = stub_copy_info(stp, COMPILE_CHUNK, info,
- code+MI_COMPILE_PTR, code+MI_COMPILE_SIZE_ON_HEAP);
+ code+MI_COMPILE_PTR,
+ code+MI_COMPILE_SIZE,
+ code+MI_COMPILE_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
}
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 66f4259d20..1cdce49eef 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2844,7 +2844,7 @@ BIF_RETTYPE float_to_list_1(BIF_ALIST_1)
if (is_not_float(BIF_ARG_1))
BIF_ERROR(BIF_P, BADARG);
GET_DOUBLE(BIF_ARG_1, f);
- if ((i = sys_double_to_chars(f.fd, fbuf)) <= 0)
+ if ((i = sys_double_to_chars(f.fd, fbuf, sizeof(fbuf))) <= 0)
BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
need = i*2;
hp = HAlloc(BIF_P, need);
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 376201c309..63136d86c9 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -663,10 +663,13 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
ErtsThrPrgrData tpd_buf; /* in case we aren't a managed thread... */
#endif
int fd;
+ size_t envsz;
time_t now;
+ char env[21]; /* enough to hold any 64-bit integer */
size_t dumpnamebufsize = MAXPATHLEN;
char dumpnamebuf[MAXPATHLEN];
char* dumpname;
+ int secs;
if (ERTS_SOMEONE_IS_CRASH_DUMPING)
return;
@@ -689,9 +692,41 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
erts_writing_erl_crash_dump = 1;
#endif
- erts_sys_prepare_crash_dump();
+ envsz = sizeof(env);
+ /* ERL_CRASH_DUMP_SECONDS not set
+ * same as ERL_CRASH_DUMP_SECONDS = 0
+ * - do not write dump
+ * - do not set an alarm
+ * - break immediately
+ *
+ * ERL_CRASH_DUMP_SECONDS = 0
+ * - do not write dump
+ * - do not set an alarm
+ * - break immediately
+ *
+ * ERL_CRASH_DUMP_SECONDS < 0
+ * - do not set alarm
+ * - write dump until done
+ *
+ * ERL_CRASH_DUMP_SECONDS = S (and S positive)
+ * - Don't dump file forever
+ * - set alarm (set in sys)
+ * - write dump until alarm or file is written completely
+ */
+
+ if (erts_sys_getenv__("ERL_CRASH_DUMP_SECONDS", env, &envsz) != 0) {
+ return; /* break immediately */
+ } else {
+ secs = atoi(env);
+ }
+
+ if (secs == 0) {
+ return;
+ }
+
+ erts_sys_prepare_crash_dump(secs);
- if (erts_sys_getenv_raw("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
+ if (erts_sys_getenv__("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
dumpname = "erl_crash.dump";
else
dumpname = &dumpnamebuf[0];
diff --git a/erts/emulator/beam/code_ix.c b/erts/emulator/beam/code_ix.c
index 8025058ee0..c66d5a2f05 100644
--- a/erts/emulator/beam/code_ix.c
+++ b/erts/emulator/beam/code_ix.c
@@ -36,13 +36,13 @@
erts_smp_atomic32_t the_active_code_index;
erts_smp_atomic32_t the_staging_code_index;
-static int the_code_ix_lock = 0;
-struct code_ix_queue_item {
+static Process* code_writing_process = NULL;
+struct code_write_queue_item {
Process *p;
- struct code_ix_queue_item* next;
+ struct code_write_queue_item* next;
};
-static struct code_ix_queue_item* the_code_ix_queue = NULL;
-static erts_smp_mtx_t the_code_ix_queue_lock;
+static struct code_write_queue_item* code_write_queue = NULL;
+static erts_smp_mtx_t code_write_permission_mtx;
#ifdef ERTS_ENABLE_LOCK_CHECK
static erts_tsd_key_t has_code_write_permission;
@@ -56,7 +56,7 @@ void erts_code_ix_init(void)
*/
erts_smp_atomic32_init_nob(&the_active_code_index, 0);
erts_smp_atomic32_init_nob(&the_staging_code_index, 0);
- erts_smp_mtx_init(&the_code_ix_queue_lock, "code_ix_queue");
+ erts_smp_mtx_init(&code_write_permission_mtx, "code_write_permission");
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_tsd_key_create(&has_code_write_permission);
#endif
@@ -114,53 +114,55 @@ int erts_try_seize_code_write_permission(Process* c_p)
#ifdef ERTS_SMP
ASSERT(!erts_smp_thr_progress_is_blocking()); /* to avoid deadlock */
#endif
+ ASSERT(c_p != NULL);
- erts_smp_mtx_lock(&the_code_ix_queue_lock);
- success = !the_code_ix_lock;
+ erts_smp_mtx_lock(&code_write_permission_mtx);
+ success = (code_writing_process == NULL);
if (success) {
- the_code_ix_lock = 1;
+ code_writing_process = c_p;
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_tsd_set(has_code_write_permission, (void *) 1);
#endif
}
else { /* Already locked */
- struct code_ix_queue_item* qitem;
+ struct code_write_queue_item* qitem;
+ ASSERT(code_writing_process != c_p);
qitem = erts_alloc(ERTS_ALC_T_CODE_IX_LOCK_Q, sizeof(*qitem));
qitem->p = c_p;
erts_smp_proc_inc_refc(c_p);
- qitem->next = the_code_ix_queue;
- the_code_ix_queue = qitem;
+ qitem->next = code_write_queue;
+ code_write_queue = qitem;
erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
}
- erts_smp_mtx_unlock(&the_code_ix_queue_lock);
+ erts_smp_mtx_unlock(&code_write_permission_mtx);
return success;
}
void erts_release_code_write_permission(void)
{
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
- erts_smp_mtx_lock(&the_code_ix_queue_lock);
- while (the_code_ix_queue != NULL) { /* unleash the entire herd */
- struct code_ix_queue_item* qitem = the_code_ix_queue;
+ erts_smp_mtx_lock(&code_write_permission_mtx);
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
+ while (code_write_queue != NULL) { /* unleash the entire herd */
+ struct code_write_queue_item* qitem = code_write_queue;
erts_smp_proc_lock(qitem->p, ERTS_PROC_LOCK_STATUS);
if (!ERTS_PROC_IS_EXITING(qitem->p)) {
erts_resume(qitem->p, ERTS_PROC_LOCK_STATUS);
}
erts_smp_proc_unlock(qitem->p, ERTS_PROC_LOCK_STATUS);
- the_code_ix_queue = qitem->next;
+ code_write_queue = qitem->next;
erts_smp_proc_dec_refc(qitem->p);
erts_free(ERTS_ALC_T_CODE_IX_LOCK_Q, qitem);
}
- the_code_ix_lock = 0;
+ code_writing_process = NULL;
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_tsd_set(has_code_write_permission, (void *) 0);
#endif
- erts_smp_mtx_unlock(&the_code_ix_queue_lock);
+ erts_smp_mtx_unlock(&code_write_permission_mtx);
}
#ifdef ERTS_ENABLE_LOCK_CHECK
-int erts_is_code_ix_locked(void)
+int erts_has_code_write_permission(void)
{
- return the_code_ix_lock && erts_tsd_get(has_code_write_permission);
+ return (code_writing_process != NULL) && erts_tsd_get(has_code_write_permission);
}
#endif
diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h
index 6b2680044e..bc10e956f5 100644
--- a/erts/emulator/beam/code_ix.h
+++ b/erts/emulator/beam/code_ix.h
@@ -116,7 +116,7 @@ void erts_commit_staging_code_ix(void);
void erts_abort_staging_code_ix(void);
#ifdef ERTS_ENABLE_LOCK_CHECK
-int erts_is_code_ix_locked(void);
+int erts_has_code_write_permission(void);
#endif
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index ba73ca6da7..3eee53eba3 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -1675,7 +1675,7 @@ erts_alc_fatal_error(int error, int func, ErtsAlcType_t n, ...)
t_str = type_no_str(n);
if (!t_str) {
- sprintf(buf, "%d", (int) n);
+ erts_snprintf(buf, sizeof(buf), "%d", (int) n);
t_str = buf;
}
@@ -3572,12 +3572,12 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func)
ftype = type_no_str(found_type);
if (!ftype) {
- sprintf(fbuf, "%d", (int) found_type);
+ erts_snprintf(fbuf, sizeof(fbuf), "%d", (int) found_type);
ftype = fbuf;
}
otype = type_no_str(n);
if (!otype) {
- sprintf(obuf, "%d", (int) n);
+ erts_snprintf(obuf, sizeof(obuf), "%d", (int) n);
otype = obuf;
}
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 831e05493a..1062d4379b 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -58,7 +58,7 @@ BIF_RETTYPE os_getpid_0(BIF_ALIST_0)
char pid_string[21]; /* enough for a 64 bit number */
int n;
Eterm* hp;
- sys_get_pid(pid_string); /* In sys.c */
+ sys_get_pid(pid_string, sizeof(pid_string)); /* In sys.c */
n = sys_strlen(pid_string);
hp = HAlloc(BIF_P, n*2);
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 06cec1795d..805d788177 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -58,10 +58,17 @@ static struct { /* Protected by code write permission */
int local;
BpFunctions f; /* Local functions */
BpFunctions e; /* Export entries */
+#ifdef ERTS_SMP
+ Process* stager;
+ ErtsThrPrgrLaterOp lop;
+#endif
} finish_bp;
static Eterm
trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist);
+#ifdef ERTS_SMP
+static void smp_bp_finisher(void* arg);
+#endif
static BIF_RETTYPE
system_monitor(Process *p, Eterm monitor_pid, Eterm list);
@@ -350,7 +357,10 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
#ifdef ERTS_SMP
if (finish_bp.current >= 0) {
ASSERT(matches >= 0);
- erts_notify_finish_breakpointing(p);
+ ASSERT(finish_bp.stager == NULL);
+ finish_bp.stager = p;
+ erts_schedule_thr_prgr_later_op(smp_bp_finisher, NULL, &finish_bp.lop);
+ erts_smp_proc_inc_refc(p);
erts_suspend(p, ERTS_PROC_LOCK_MAIN, NULL);
ERTS_BIF_YIELD_RETURN(p, make_small(matches));
}
@@ -366,6 +376,29 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
}
}
+#ifdef ERTS_SMP
+static void smp_bp_finisher(void* null)
+{
+ if (erts_finish_breakpointing()) { /* Not done */
+ /* Arrange for being called again */
+ erts_schedule_thr_prgr_later_op(smp_bp_finisher, NULL, &finish_bp.lop);
+ }
+ else { /* Done */
+ Process* p = finish_bp.stager;
+#ifdef DEBUG
+ finish_bp.stager = NULL;
+#endif
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ }
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ erts_smp_proc_dec_refc(p);
+ erts_release_code_write_permission();
+ }
+}
+#endif /* ERTS_SMP */
+
void
erts_get_default_trace_pattern(int *trace_pattern_is_on,
Binary **match_spec,
@@ -373,7 +406,7 @@ erts_get_default_trace_pattern(int *trace_pattern_is_on,
struct trace_pattern_flags *trace_pattern_flags,
Eterm *meta_tracer_pid)
{
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked() ||
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission() ||
erts_smp_thr_progress_is_blocking());
if (trace_pattern_is_on)
*trace_pattern_is_on = erts_default_trace_pattern_is_on;
@@ -389,7 +422,7 @@ erts_get_default_trace_pattern(int *trace_pattern_is_on,
int erts_is_default_trace_enabled(void)
{
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked() ||
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission() ||
erts_smp_thr_progress_is_blocking());
return erts_default_trace_pattern_is_on;
}
@@ -1530,7 +1563,7 @@ erts_set_trace_pattern(Process*p, Eterm* mfa, int specified,
int
erts_finish_breakpointing(void)
{
- ERTS_SMP_LC_ASSERT(erts_is_code_ix_locked());
+ ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
/*
* Memory barriers will be issued for all processes *before*
@@ -1538,7 +1571,6 @@ erts_finish_breakpointing(void)
* are blocked, in which case memory barriers will be issued
* when they are awaken.)
*/
-
switch (finish_bp.current++) {
case 0:
/*
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 42907e2e84..0c9ca83ce4 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -2480,7 +2480,7 @@ Eterm db_format_dmc_err_info(Process *p, DMCErrInfo *ei)
vnum = tmp->variable;
}
if (vnum >= 0)
- sprintf(buff,tmp->error_string, vnum);
+ erts_snprintf(buff,sizeof(buff)+20,tmp->error_string, vnum);
else
strcpy(buff,tmp->error_string);
sl = strlen(buff);
@@ -4485,7 +4485,9 @@ static DMCRet dmc_fun(DMCContext *context,
if (context->err_info != NULL) {
/* Ugly, should define a better RETURN_TERM_ERROR interface... */
char buff[100];
- sprintf(buff, "Function %%T/%d does_not_exist.", (int)a - 1);
+ erts_snprintf(buff, sizeof(buff),
+ "Function %%T/%d does_not_exist.",
+ (int)a - 1);
RETURN_TERM_ERROR(buff, p[1], context, *constant);
} else {
return retFail;
@@ -4500,7 +4502,7 @@ static DMCRet dmc_fun(DMCContext *context,
if (context->err_info != NULL) {
/* Ugly, should define a better RETURN_TERM_ERROR interface... */
char buff[100];
- sprintf(buff,
+ erts_snprintf(buff, sizeof(buff),
"Function %%T/%d cannot be called in this context.",
(int)a - 1);
RETURN_TERM_ERROR(buff, p[1], context, *constant);
@@ -4764,7 +4766,7 @@ static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info)
for (j = 0; j < x && DMC_PEEK(heap,j) != n; ++j)
;
ASSERT(j < x);
- sprintf(buff+1,"%u", (unsigned) j);
+ erts_snprintf(buff+1, sizeof(buff) - 1, "%u", (unsigned) j);
/* Yes, writing directly into terms, they ARE off heap */
*p = am_atom_put(buff, strlen(buff));
}
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 11fed4079d..314d2f6a9c 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -93,7 +93,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "proc_msgq", "pid" },
{ "dist_entry", "address" },
{ "dist_entry_links", "address" },
- { "code_ix_queue", NULL },
+ { "code_write_permission", NULL },
{ "proc_status", "pid" },
{ "proc_tab", NULL },
{ "ports_snapshot", NULL },
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index e397f075d1..d5b7d01048 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -1096,7 +1096,6 @@ erts_send_message(Process* sender,
}
BM_SWAP_TIMER(send,system);
#endif /* #ifndef ERTS_SMP */
- return;
}
return res;
}
diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c
index 358c67bf20..5a6fb8589f 100644
--- a/erts/emulator/beam/erl_mtrace.c
+++ b/erts/emulator/beam/erl_mtrace.c
@@ -611,7 +611,7 @@ void erts_mtrace_init(char *receiver, char *nodename)
if (erts_sock_gethostname(hostname, MAXHOSTNAMELEN) != 0)
hostname[0] = '\0';
hostname[MAXHOSTNAMELEN-1] = '\0';
- sys_get_pid(pid);
+ sys_get_pid(pid, sizeof(pid));
write_trace_header(nodename ? nodename : "", pid, hostname);
erts_mtrace_update_heap_size();
}
diff --git a/erts/emulator/beam/erl_posix_str.c b/erts/emulator/beam/erl_posix_str.c
index 02db10905b..deb7e3e173 100644
--- a/erts/emulator/beam/erl_posix_str.c
+++ b/erts/emulator/beam/erl_posix_str.c
@@ -619,6 +619,7 @@ erl_errno_id(error)
case WSAEINVALIDPROVIDER: return "einvalidprovider";
#endif
#ifdef WSAEPROVIDERFAILEDINIT
+ /* You could get this if SYSTEMROOT env variable is set incorrectly */
case WSAEPROVIDERFAILEDINIT: return "eproviderfailedinit";
#endif
#ifdef WSASYSCALLFAILURE
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index c58bf40435..09169ba914 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -530,10 +530,6 @@ dbg_chk_aux_work_val(erts_aint32_t value)
#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
valid |= ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
#endif
-#ifdef ERTS_SMP
- valid |= ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
- valid |= ERTS_SSI_AUX_WORK_FINISH_BP;
-#endif
#ifdef ERTS_SSI_AUX_WORK_REAP_PORTS
valid |= ERTS_SSI_AUX_WORK_REAP_PORTS;
#endif
@@ -1450,92 +1446,6 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp,
#endif /* ERTS_USE_ASYNC_READY_Q */
-#ifdef ERTS_SMP
-void
-erts_notify_code_ix_activation(Process* p, ErtsThrPrgrVal later)
-{
- ErtsAuxWorkData* awdp = &p->scheduler_data->aux_work_data;
- ASSERT(awdp->code_ix_activation.code_stager == NULL);
- awdp->code_ix_activation.code_stager = p;
- awdp->code_ix_activation.thr_prgr = later;
- erts_smp_proc_inc_refc(p);
- set_aux_work_flags_wakeup_relb(p->scheduler_data->ssi,
- ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION);
-}
-
-static erts_aint32_t
-handle_code_ix_activation(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
-{
- Process* p;
- if (!erts_thr_progress_has_reached(awdp->code_ix_activation.thr_prgr)) {
- return aux_work & ~ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
- }
- unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION);
- p = awdp->code_ix_activation.code_stager;
- ASSERT(p);
-#ifdef DEBUG
- awdp->code_ix_activation.code_stager = NULL;
-#endif
- erts_commit_staging_code_ix();
- erts_release_code_write_permission();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
- if (!ERTS_PROC_IS_EXITING(p)) {
- erts_resume(p, ERTS_PROC_LOCK_STATUS);
- }
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_proc_dec_refc(p);
- return aux_work & ~ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
-}
-#endif /* ERTS_SMP */
-
-#ifdef ERTS_SMP
-void
-erts_notify_finish_breakpointing(Process* p)
-{
- ErtsAuxWorkData* awdp = &p->scheduler_data->aux_work_data;
-
- ASSERT(awdp->bp_ix_activation.stager == NULL);
- awdp->bp_ix_activation.stager = p;
- awdp->bp_ix_activation.thr_prgr = erts_thr_progress_later(awdp->esdp);
- erts_thr_progress_wakeup(awdp->esdp, awdp->bp_ix_activation.thr_prgr);
- erts_smp_proc_inc_refc(p);
- set_aux_work_flags_wakeup_relb(p->scheduler_data->ssi,
- ERTS_SSI_AUX_WORK_FINISH_BP);
-}
-
-static erts_aint32_t
-handle_finish_bp(ErtsAuxWorkData* awdp, erts_aint32_t aux_work)
-{
- ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
-
- if (!erts_thr_progress_has_reached_this(current,
- awdp->bp_ix_activation.thr_prgr)) {
- return aux_work & ~ERTS_SSI_AUX_WORK_FINISH_BP;
- }
- if (erts_finish_breakpointing()) { /* Not done */
- /* Arrange for being called again */
- awdp->bp_ix_activation.thr_prgr =
- erts_thr_progress_later(awdp->esdp);
- erts_thr_progress_wakeup(awdp->esdp, awdp->bp_ix_activation.thr_prgr);
- } else { /* Done */
- Process* p;
-
- unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_FINISH_BP);
- p = awdp->bp_ix_activation.stager;
-#ifdef DEBUG
- awdp->bp_ix_activation.stager = NULL;
-#endif
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
- if (!ERTS_PROC_IS_EXITING(p)) {
- erts_resume(p, ERTS_PROC_LOCK_STATUS);
- }
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_proc_dec_refc(p);
- erts_release_code_write_permission();
- }
- return aux_work & ~ERTS_SSI_AUX_WORK_FINISH_BP;
-}
-#endif /* ERTS_SMP */
static ERTS_INLINE erts_aint32_t
handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
@@ -1670,6 +1580,9 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
if (!erts_thr_progress_has_reached_this(current, lop->later))
return aux_work & ~ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP;
awdp->later_op.first = lop->next;
+ if (!awdp->later_op.first) {
+ awdp->later_op.last = NULL;
+ }
lop->func(lop->data);
if (!awdp->later_op.first) {
awdp->later_op.last = NULL;
@@ -1981,19 +1894,9 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
handle_mseg_cache_check);
#endif
-#ifdef ERTS_SMP
- HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION,
- handle_code_ix_activation);
-#endif
-
HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_REAP_PORTS,
handle_reap_ports);
-#ifdef ERTS_SMP
- HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_FINISH_BP,
- handle_finish_bp);
-#endif
-
ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
#ifdef ERTS_SMP
@@ -9453,7 +9356,7 @@ stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg)
erts_print(to, to_arg, "\n%p ", sp);
} else {
char sbuf[16];
- sprintf(sbuf, "y(%d)", yreg);
+ erts_snprintf(sbuf, sizeof(sbuf), "y(%d)", yreg);
erts_print(to, to_arg, "%-8s ", sbuf);
yreg++;
}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 1436e246d6..fa6961e8a4 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -283,9 +283,7 @@ typedef enum {
#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 10)
#define ERTS_SSI_AUX_WORK_SET_TMO (((erts_aint32_t) 1) << 11)
#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK (((erts_aint32_t) 1) << 12)
-#define ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION (((erts_aint32_t) 1) << 13)
-#define ERTS_SSI_AUX_WORK_REAP_PORTS (((erts_aint32_t) 1) << 14)
-#define ERTS_SSI_AUX_WORK_FINISH_BP (((erts_aint32_t) 1) << 15)
+#define ERTS_SSI_AUX_WORK_REAP_PORTS (((erts_aint32_t) 1) << 13)
typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo;
@@ -480,14 +478,6 @@ typedef struct {
#endif
#ifdef ERTS_SMP
struct {
- Process* code_stager;
- ErtsThrPrgrVal thr_prgr;
- } code_ix_activation;
- struct {
- Process* stager;
- ErtsThrPrgrVal thr_prgr;
- } bp_ix_activation;
- struct {
int *sched2jix;
int jix;
ErtsDelayedAuxWorkWakeupJob *job;
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index 964dc1ae3e..542c5ed0d9 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -323,7 +323,7 @@ heap_dump(int to, void *to_arg, Eterm x)
int i;
GET_DOUBLE_DATA((ptr+1), f);
- i = sys_double_to_chars(f.fd, (char*) sbuf);
+ i = sys_double_to_chars(f.fd, (char*) sbuf, sizeof(sbuf));
sys_memset(sbuf+i, 0, 31-i);
erts_print(to, to_arg, "F%X:%s\n", i, sbuf);
*ptr = OUR_NIL;
diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c
index 7777ba1d3d..84a8270d06 100644
--- a/erts/emulator/beam/erl_process_lock.c
+++ b/erts/emulator/beam/erl_process_lock.c
@@ -1587,7 +1587,7 @@ erts_proc_lc_chk_no_proc_locks(char *file, int line)
lc_id.proc_lock_msgq,
lc_id.proc_lock_status};
erts_lc_have_lock_ids(resv, ids, 4);
- if (resv[0] || resv[1] || resv[2] || resv[3]) {
+ if (!ERTS_IS_CRASH_DUMPING && (resv[0] || resv[1] || resv[2] || resv[3])) {
erts_lc_fail("%s:%d: Thread has process locks locked when expected "
"not to have any process locks locked",
file, line);
diff --git a/erts/emulator/beam/erl_resolv_dns.c b/erts/emulator/beam/erl_resolv_dns.c
deleted file mode 100644
index 9d76fa89f8..0000000000
--- a/erts/emulator/beam/erl_resolv_dns.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. 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%
- */
-
-/*
- * Set this to non-zero value if DNS should be used.
- */
-int erl_use_resolver = 1;
diff --git a/erts/emulator/beam/erl_resolv_nodns.c b/erts/emulator/beam/erl_resolv_nodns.c
deleted file mode 100644
index f14ab68e27..0000000000
--- a/erts/emulator/beam/erl_resolv_nodns.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. 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%
- */
-
-/*
- * Set this to non-zero value if DNS should be used.
- */
-int erl_use_resolver = 0;
diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c
index f77e8b798f..bf7774f882 100644
--- a/erts/emulator/beam/erl_term.c
+++ b/erts/emulator/beam/erl_term.c
@@ -105,7 +105,7 @@ unsigned tag_val_def(Wterm x)
break;
}
}
- sprintf(msg, "tag_val_def: %#lx", (unsigned long) x);
+ erts_snprintf(msg, sizeof(msg), "tag_val_def: %#lx", (unsigned long) x);
et_abort(msg, file, line);
#undef file
#undef line
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 16a987472a..ab1065aaa1 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1850,8 +1850,8 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags,
} else {
*ep++ = FLOAT_EXT;
- /* now the sprintf which does the work */
- i = sys_double_to_chars(f.fd, (char*) ep);
+ /* now the erts_snprintf which does the work */
+ i = sys_double_to_chars(f.fd, (char*) ep, (size_t)31);
/* Don't leave garbage after the float! (Bad practice in general,
* and Purify complains.)
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 1503d793ab..4c0d3421c8 100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -999,6 +999,9 @@ Uint erts_port_ioq_size(Port *pp);
void erts_stale_drv_select(Eterm, ErlDrvEvent, int, int);
void erts_port_cleanup(Port *);
void erts_fire_port_monitor(Port *prt, Eterm ref);
+
+Port *erts_get_heart_port(void);
+
#ifdef ERTS_SMP
void erts_smp_xports_unlock(Port *);
#endif
diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c
index 25d5cce0f3..c981a0a55e 100644
--- a/erts/emulator/beam/index.c
+++ b/erts/emulator/beam/index.c
@@ -82,7 +82,8 @@ index_put_entry(IndexTable* t, void* tmpl)
if (ix >= t->size) {
Uint sz;
if (ix >= t->limit) {
- erl_exit(1, "no more index entries in %s (max=%d)\n",
+ /* A core dump is unnecessary */
+ erl_exit(ERTS_DUMP_EXIT, "no more index entries in %s (max=%d)\n",
t->htable.name, t->limit);
}
sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index dec51f3be5..60b9238d38 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1128,7 +1128,7 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
Uint size;
int fpe_was_unmasked;
- ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p) || ERTS_IS_CRASH_DUMPING);
ERTS_SMP_CHK_NO_PROC_LOCKS;
p->caller = caller_id;
@@ -5258,3 +5258,27 @@ erl_drv_getenv(char *key, char *value, size_t *value_size)
{
return erts_sys_getenv_raw(key, value, value_size);
}
+
+/* get heart_port
+ * used by erl_crash_dump
+ * - uses the fact that heart_port is registered when starting heart
+ */
+
+Port *erts_get_heart_port() {
+
+ Port* port;
+ Uint ix;
+
+ for(ix = 0; ix < erts_max_ports; ix++) {
+ port = &erts_port[ix];
+ /* only examine undead or alive ports */
+ if (port->status & ERTS_PORT_SFLGS_DEAD)
+ continue;
+ /* immediate atom compare */
+ if (port->reg && port->reg->name == am_heart_port) {
+ return port;
+ }
+ }
+
+ return NULL;
+}
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 1ef71cda79..01856007ee 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -144,7 +144,7 @@ erts_put_module(Eterm mod)
ASSERT(is_atom(mod));
ERTS_SMP_LC_ASSERT(erts_initialized == 0
- || erts_is_code_ix_locked());
+ || erts_has_code_write_permission());
mod_tab = &module_tables[erts_staging_code_ix()];
e.module = atom_val(mod);
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 2c65ce91d1..8957bb5bde 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -644,7 +644,7 @@ void erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec);
void erts_sys_main_thread(void);
#endif
-extern void erts_sys_prepare_crash_dump(void);
+extern void erts_sys_prepare_crash_dump(int secs);
extern void erts_sys_pre_init(void);
extern void erl_sys_init(void);
extern void erl_sys_args(int *argc, char **argv);
@@ -691,8 +691,8 @@ void fini_getenv_state(GETENV_STATE *);
/* xxxP */
void init_sys_float(void);
int sys_chars_to_double(char*, double*);
-int sys_double_to_chars(double, char*);
-void sys_get_pid(char *);
+int sys_double_to_chars(double, char*, size_t);
+void sys_get_pid(char *, size_t);
/* erts_sys_putenv() returns, 0 on success and a value != 0 on failure. */
int erts_sys_putenv(char *key, char *value);
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 8981050228..3210ffa92a 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -10162,6 +10162,7 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
}
new_udesc->inet.state = INET_STATE_CONNECTED;
new_udesc->inet.stype = SOCK_STREAM;
+ SET_NONBLOCKING(new_udesc->inet.s);
inet_reply_ok_port(desc, new_udesc->inet.dport);
(*rbuf)[0] = INET_REP;
diff --git a/erts/emulator/drivers/win32/registry_drv.c b/erts/emulator/drivers/win32/registry_drv.c
index 1fad34e380..5b200ebd32 100644
--- a/erts/emulator/drivers/win32/registry_drv.c
+++ b/erts/emulator/drivers/win32/registry_drv.c
@@ -344,7 +344,7 @@ fix_value_result(RegPort* rp, LONG result, DWORD type,
#ifdef DEBUG
if (ok != ERROR_SUCCESS) {
char buff[256];
- sprintf(buff,"Failure in registry_drv line %d, error = %d",
+ erts_snprintf(buff, sizeof(buff), "Failure in registry_drv line %d, error = %d",
__LINE__, GetLastError());
MessageBox(NULL, buff, "Internal error", MB_OK);
ASSERT(ok == ERROR_SUCCESS);
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index c1fa00b4ea..b485dbf784 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -58,7 +58,6 @@
#define __DARWIN__ 1
#endif
-
#ifdef USE_THREADS
#include "erl_threads.h"
#endif
@@ -71,7 +70,6 @@ static erts_smp_rwmtx_t environ_rwmtx;
#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
* vector sock_sendv().
*/
-
/*
* Don't need global.h, but bif_table.h (included by bif.h),
* won't compile otherwise
@@ -123,6 +121,15 @@ struct ErtsSysReportExit_ {
#endif
};
+/* This data is shared by these drivers - initialized by spawn_init() */
+static struct driver_data {
+ int port_num, ofd, packet_bytes;
+ ErtsSysReportExit *report_exit;
+ int pid;
+ int alive;
+ int status;
+} *driver_data; /* indexed by fd */
+
static ErtsSysReportExit *report_exit_list;
#if CHLDWTHR && !defined(ERTS_SMP)
static ErtsSysReportExit *report_exit_transit_list;
@@ -570,7 +577,7 @@ erl_sys_init(void)
+ 1);
child_setup_prog = erts_alloc(ERTS_ALC_T_CS_PROG_PATH, csp_path_sz);
erts_smp_atomic_add_nob(&sys_misc_mem_sz, csp_path_sz);
- sprintf(child_setup_prog,
+ erts_snprintf(child_setup_prog, csp_path_sz,
"%s%c%s",
bindir,
DIR_SEPARATOR_CHAR,
@@ -680,17 +687,40 @@ static RETSIGTYPE break_handler(int sig)
#endif /* 0 */
static ERTS_INLINE void
-prepare_crash_dump(void)
+prepare_crash_dump(int secs)
{
+#define NUFBUF (3)
int i, max;
char env[21]; /* enough to hold any 64-bit integer */
size_t envsz;
+ DeclareTmpHeapNoproc(heap,NUFBUF);
+ Port *heart_port;
+ Eterm *hp = heap;
+ Eterm list = NIL;
+ int heart_fd[2] = {-1,-1};
+
+ UseTmpHeapNoproc(NUFBUF);
if (ERTS_PREPARED_CRASH_DUMP)
return; /* We have already been called */
+ heart_port = erts_get_heart_port();
+ if (heart_port) {
+ /* hearts input fd
+ * We "know" drv_data is the in_fd since the port is started with read|write
+ */
+ heart_fd[0] = (int)heart_port->drv_data;
+ heart_fd[1] = (int)driver_data[heart_fd[0]].ofd;
+
+ list = CONS(hp, make_small(8), list); hp += 2;
+
+ /* send to heart port, CMD = 8, i.e. prepare crash dump =o */
+ erts_write_to_port(ERTS_INVALID_PID, heart_port, list);
+ }
+
/* Make sure we unregister at epmd (unknown fd) and get at least
one free filedescriptor (for erl_crash.dump) */
+
max = max_files;
if (max < 1024)
max = 1024;
@@ -704,11 +734,15 @@ prepare_crash_dump(void)
if (i == async_fd[0] || i == async_fd[1])
continue;
#endif
+ /* We don't want to close our heart yet ... */
+ if (i == heart_fd[0] || i == heart_fd[1])
+ continue;
+
close(i);
}
envsz = sizeof(env);
- i = erts_sys_getenv_raw("ERL_CRASH_DUMP_NICE", env, &envsz);
+ i = erts_sys_getenv__("ERL_CRASH_DUMP_NICE", env, &envsz);
if (i >= 0) {
int nice_val;
nice_val = i != 0 ? 0 : atoi(env);
@@ -717,21 +751,21 @@ prepare_crash_dump(void)
}
erts_silence_warn_unused_result(nice(nice_val));
}
-
- envsz = sizeof(env);
- i = erts_sys_getenv_raw("ERL_CRASH_DUMP_SECONDS", env, &envsz);
- if (i >= 0) {
- unsigned sec;
- sec = (unsigned) i != 0 ? 0 : atoi(env);
- alarm(sec);
- }
+ /* Positive secs means an alarm must be set
+ * 0 or negative means no alarm
+ */
+ if (secs > 0) {
+ alarm((unsigned int)secs);
+ }
+ UnUseTmpHeapNoproc(NUFBUF);
+#undef NUFBUF
}
void
-erts_sys_prepare_crash_dump(void)
+erts_sys_prepare_crash_dump(int secs)
{
- prepare_crash_dump();
+ prepare_crash_dump(secs);
}
static ERTS_INLINE void
@@ -773,7 +807,7 @@ sigusr1_exit(void)
is hung somewhere, so it won't be able to poll any flag we set here.
*/
ERTS_SET_GOT_SIGUSR1;
- prepare_crash_dump();
+ prepare_crash_dump((int)0);
erl_exit(1, "Received SIGUSR1\n");
}
@@ -1021,15 +1055,6 @@ void fini_getenv_state(GETENV_STATE *state)
#define ERTS_SYS_READ_BUF_SZ (64*1024)
-/* This data is shared by these drivers - initialized by spawn_init() */
-static struct driver_data {
- int port_num, ofd, packet_bytes;
- ErtsSysReportExit *report_exit;
- int pid;
- int alive;
- int status;
-} *driver_data; /* indexed by fd */
-
/* Driver interfaces */
static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
@@ -1532,12 +1557,13 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* op
}
#if !DISABLE_VFORK
}
+#define ENOUGH_BYTES (44)
else { /* Use vfork() */
char **cs_argv= erts_alloc(ERTS_ALC_T_TMP,(CS_ARGV_NO_OF_ARGS + 1)*
sizeof(char *));
- char fd_close_range[44]; /* 44 bytes are enough to */
- char dup2_op[CS_ARGV_NO_OF_DUP2_OPS][44]; /* hold any "%d:%d" string */
- /* on a 64-bit machine. */
+ char fd_close_range[ENOUGH_BYTES]; /* 44 bytes are enough to */
+ char dup2_op[CS_ARGV_NO_OF_DUP2_OPS][ENOUGH_BYTES]; /* hold any "%d:%d" string */
+ /* on a 64-bit machine. */
/* Setup argv[] for the child setup program (implemented in
erl_child_setup.c) */
@@ -1545,23 +1571,23 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* op
if (opts->use_stdio) {
if (opts->read_write & DO_READ){
/* stdout for process */
- sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 1);
+ erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 1);
if(opts->redir_stderr)
/* stderr for process */
- sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 2);
+ erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 2);
}
if (opts->read_write & DO_WRITE)
/* stdin for process */
- sprintf(&dup2_op[i++][0], "%d:%d", ofd[0], 0);
+ erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ofd[0], 0);
} else { /* XXX will fail if ofd[0] == 4 (unlikely..) */
if (opts->read_write & DO_READ)
- sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 4);
+ erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 4);
if (opts->read_write & DO_WRITE)
- sprintf(&dup2_op[i++][0], "%d:%d", ofd[0], 3);
+ erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ofd[0], 3);
}
for (; i < CS_ARGV_NO_OF_DUP2_OPS; i++)
strcpy(&dup2_op[i][0], "-");
- sprintf(fd_close_range, "%d:%d", opts->use_stdio ? 3 : 5, max_files-1);
+ erts_snprintf(fd_close_range, ENOUGH_BYTES, "%d:%d", opts->use_stdio ? 3 : 5, max_files-1);
cs_argv[CS_ARGV_PROGNAME_IX] = child_setup_prog;
cs_argv[CS_ARGV_WD_IX] = opts->wd ? opts->wd : ".";
@@ -1612,6 +1638,7 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* op
}
erts_free(ERTS_ALC_T_TMP,cs_argv);
}
+#undef ENOUGH_BYTES
#endif
erts_sched_bind_atfork_parent(unbind);
@@ -2355,10 +2382,10 @@ void erts_do_break_handling(void)
** no interpretatione of this should be done by the rest of the
** emulator. The buffer should be at least 21 bytes long.
*/
-void sys_get_pid(char *buffer){
+void sys_get_pid(char *buffer, size_t buffer_size){
pid_t p = getpid();
/* Assume the pid is scalar and can rest in an unsigned long... */
- sprintf(buffer,"%lu",(unsigned long) p);
+ erts_snprintf(buffer, buffer_size, "%lu",(unsigned long) p);
}
int
@@ -2417,6 +2444,15 @@ erts_sys_getenv_raw(char *key, char *value, size_t *size) {
return erts_sys_getenv(key, value, size);
}
+/*
+ * erts_sys_getenv
+ * returns:
+ * -1, if environment key is not set with a value
+ * 0, if environment key is set and value fits into buffer size
+ * 1, if environment key is set but does not fit into buffer size
+ * size is set with the needed buffer size value
+ */
+
int
erts_sys_getenv(char *key, char *value, size_t *size)
{
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index 8ec7b31ce0..3fcb4d88dc 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -745,18 +745,18 @@ void erts_sys_unblock_fpe(int unmasked)
*/
int
-sys_double_to_chars(double fp, char *buf)
+sys_double_to_chars(double fp, char *buffer, size_t buffer_size)
{
- char *s = buf;
+ char *s = buffer;
- (void) sprintf(buf, "%.20e", fp);
+ (void) erts_snprintf(buffer, buffer_size, "%.20e", fp);
/* Search upto decimal point */
if (*s == '+' || *s == '-') s++;
while (ISDIGIT(*s)) s++;
if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */
/* Scan to end of string */
while (*s) s++;
- return s-buf; /* i.e strlen(buf) */
+ return s-buffer; /* i.e strlen(buffer) */
}
/* Float conversion */
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 6894d682e7..47d12ed5fe 100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -256,10 +256,25 @@ void erl_sys_args(int* argc, char** argv)
}
void
-erts_sys_prepare_crash_dump(void)
+erts_sys_prepare_crash_dump(int secs)
{
+ Port *heart_port;
+ Eterm heap[3];
+ Eterm *hp = heap;
+ Eterm list = NIL;
+
+ heart_port = erts_get_heart_port();
+
+ if (heart_port) {
+
+ list = CONS(hp, make_small(8), list); hp += 2;
+
+ /* send to heart port, CMD = 8, i.e. prepare crash dump =o */
+ erts_write_to_port(NIL, heart_port, list);
+ }
+
/* Windows - free file descriptors are hopefully available */
- return;
+ /* Alarm not used on windows */
}
static void
@@ -420,6 +435,8 @@ typedef struct async_io {
HANDLE ioAllowed; /* The thread will wait for this event
* before starting a new read or write.
*/
+ HANDLE flushEvent; /* Used to signal that a flush should be done. */
+ HANDLE flushReplyEvent; /* Used to signal that a flush has been done. */
DWORD pendingError; /* Used to delay presentating an error to Erlang
* until the check_io function is entered.
*/
@@ -878,6 +895,8 @@ init_async_io(AsyncIo* aio, int use_threads)
aio->ov.Offset = 0L;
aio->ov.OffsetHigh = 0L;
aio->ioAllowed = NULL;
+ aio->flushEvent = NULL;
+ aio->flushReplyEvent = NULL;
aio->pendingError = 0;
aio->bytesTransferred = 0;
#ifdef ERTS_SMP
@@ -890,6 +909,12 @@ init_async_io(AsyncIo* aio, int use_threads)
aio->ioAllowed = CreateAutoEvent(FALSE);
if (aio->ioAllowed == NULL)
return -1;
+ aio->flushEvent = CreateAutoEvent(FALSE);
+ if (aio->flushEvent == NULL)
+ return -1;
+ aio->flushReplyEvent = CreateAutoEvent(FALSE);
+ if (aio->flushReplyEvent == NULL)
+ return -1;
}
return 0;
}
@@ -923,6 +948,14 @@ release_async_io(AsyncIo* aio, ErlDrvPort port_num)
if (aio->ioAllowed != NULL)
CloseHandle(aio->ioAllowed);
aio->ioAllowed = NULL;
+
+ if (aio->flushEvent != NULL)
+ CloseHandle(aio->flushEvent);
+ aio->flushEvent = NULL;
+
+ if (aio->flushReplyEvent != NULL)
+ CloseHandle(aio->flushReplyEvent);
+ aio->flushReplyEvent = NULL;
}
/* ----------------------------------------------------------------------
@@ -2083,16 +2116,26 @@ threaded_writer(LPVOID param)
AsyncIo* aio = (AsyncIo *) param;
HANDLE thread = GetCurrentThread();
char* buf;
- DWORD numToWrite;
+ DWORD numToWrite, handle;
int ok;
+ HANDLE handles[2];
+ handles[0] = aio->ioAllowed;
+ handles[1] = aio->flushEvent;
for (;;) {
- WaitForSingleObject(aio->ioAllowed, INFINITE);
+ handle = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (aio->flags & DF_EXIT_THREAD)
break;
+
buf = OV_BUFFER_PTR(aio);
numToWrite = OV_NUM_TO_READ(aio);
aio->pendingError = 0;
+
+ if (handle == (WAIT_OBJECT_0 + 1) && numToWrite == 0) {
+ SetEvent(aio->flushReplyEvent);
+ continue;
+ }
+
ok = WriteFile(aio->fd, buf, numToWrite, &aio->bytesTransferred, NULL);
if (!ok) {
aio->pendingError = GetLastError();
@@ -2127,7 +2170,11 @@ threaded_writer(LPVOID param)
}
}
}
- SetEvent(aio->ov.hEvent);
+ OV_NUM_TO_READ(aio) = 0;
+ if (handle == (WAIT_OBJECT_0 + 1))
+ SetEvent(aio->flushReplyEvent);
+ else
+ SetEvent(aio->ov.hEvent);
if (aio->pendingError != NO_ERROR || aio->bytesTransferred == 0)
break;
if (aio->flags & DF_EXIT_THREAD)
@@ -2193,6 +2240,43 @@ fd_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
if ((dp = new_driver_data(port_num, opts->packet_bytes, 2, TRUE)) == NULL)
return ERL_DRV_ERROR_GENERAL;
+ /**
+ * Here is a brief description about how the fd driver works on windows.
+ *
+ * fd_init:
+ * For each in/out fd pair a threaded_reader and threaded_writer thread is
+ * created. Within the DriverData struct each of the threads have an AsyncIO
+ * sctruct associated with it. Within AsyncIO there are two important HANDLEs,
+ * ioAllowed and ov.hEvent. ioAllowed is used to signal the threaded_* threads
+ * should read/write some data, and ov.hEvent is driver_select'ed to be used to
+ * signal that the thread is done reading/writing.
+ *
+ * The reason for the driver being threaded like this is because once the FD is open
+ * on windows, it is not possible to set the it in overlapped mode. So we have to
+ * simulate this using threads.
+ *
+ * output:
+ * When an output occurs the data to be outputted is copied to AsyncIO.ov. Then
+ * the ioAllowed HANDLE is set, ov.hEvent is cleared and the port is marked as busy.
+ * The threaded_writer thread is lying in WaitForMultipleObjects on ioAllowed, and
+ * when signalled it writes all data in AsyncIO.ov and then sets ov.hEvent so that
+ * ready_output gets triggered and (potentially) sends the reply to the port and
+ * marks the port an non-busy.
+ *
+ * input:
+ * The threaded_reader is lying waiting in ReadFile on the in fd and when a new
+ * line is written it sets ov.hEvent that new data is available and then goes
+ * and waits for ioAllowed to be set. ready_input is run when ov.hEvent is set and
+ * delivers the data to the port. Then ioAllowed is signalled again and threaded_reader
+ * goes back to ReadFile.
+ *
+ * shutdown:
+ * In order to guarantee that all io is outputted before the driver is stopped,
+ * fd_stop uses flushEvent and flushReplyEvent to make sure that there is no data
+ * in ov which needs writing before returning from fd_stop.
+ *
+ **/
+
if (!create_file_thread(&dp->in, DO_READ)) {
dp->port_num = PORT_FREE;
return ERL_DRV_ERROR_GENERAL;
@@ -2241,6 +2325,8 @@ static void fd_stop(ErlDrvData d)
(void) driver_select(dp->port_num,
(ErlDrvEvent)dp->out.ov.hEvent,
ERL_DRV_WRITE, 0);
+ SetEvent(dp->out.flushEvent);
+ WaitForSingleObject(dp->out.flushReplyEvent, INFINITE);
}
}
@@ -2764,10 +2850,10 @@ static void stop_select(ErlDrvEvent e, void* _)
** no interpretation of this should be done by the rest of the
** emulator. The buffer should be at least 21 bytes long.
*/
-void sys_get_pid(char *buffer){
+void sys_get_pid(char *buffer, size_t buffer_size){
DWORD p = GetCurrentProcessId();
/* The pid is scalar and is an unsigned long. */
- sprintf(buffer,"%lu",(unsigned long) p);
+ erts_snprintf(buffer, buffer_size, "%lu",(unsigned long) p);
}
void
@@ -3107,7 +3193,8 @@ erl_assert_error(char* expr, char* file, int line)
{
char message[1024];
- sprintf(message, "File %hs, line %d: %hs", file, line, expr);
+ erts_snprintf(message, sizeof(message),
+ "File %hs, line %d: %hs", file, line, expr);
MessageBox(GetActiveWindow(), message, "Assertion failed",
MB_OK | MB_ICONERROR);
#if 0
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index 6558ad2d99..09dad89140 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -118,18 +118,18 @@ sys_chars_to_double(char *buf, double *fp)
*/
int
-sys_double_to_chars(double fp, char *buf)
+sys_double_to_chars(double fp, char *buffer, size_t buffer_size)
{
- char *s = buf;
+ char *s = buffer;
- (void) sprintf(buf, "%.20e", fp);
+ (void) erts_snprintf(buffer, buffer_size, "%.20e", fp);
/* Search upto decimal point */
if (*s == '+' || *s == '-') s++;
while (isdigit(*s)) s++;
if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */
/* Scan to end of string */
while (*s) s++;
- return s-buf; /* i.e strlen(buf) */
+ return s-buffer; /* i.e strlen(buffer) */
}
int
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
index 13af7d861a..b214f87e4a 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
@@ -16,11 +16,19 @@
* $Id$
*/
+#include "erl_int_sizes_config.h"
+
#include "testcase_driver.h"
#include "allocator_test.h"
#include <stdio.h>
-#define SBCT (512*1024)
+#ifdef __WIN32__ && SIZEOF_VOID_P == 8
+/* Use larger threashold for win64 as block alignment
+ is 16 bytes and not 8 */
+#define SBCT ((1024*1024))
+#else
+#define SBCT ((512*1024))
+#endif
char *
testcase_name(void)
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 58e0cb4096..babdb3363f 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -626,8 +626,32 @@ safe_binary_to_term2(Config) when is_list(Config) ->
bad_terms(suite) -> [];
bad_terms(Config) when is_list(Config) ->
?line test_terms(fun corrupter/1).
-
+
+corrupter(Term) when is_function(Term);
+ is_function(hd(Term));
+ is_function(element(2,element(2,element(2,Term)))) ->
+ %% Check if lists is native compiled. If it is, we do not try to
+ %% corrupt funs as this can create some very strange behaviour.
+ %% To show the error print `Byte` in the foreach fun in corrupter/2.
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ corrupter0(Term);
+ Architecture ->
+ {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
+ case NativeChunk of
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
+ S = io_lib:format("Skipping corruption of: ~P", [Term,12]),
+ io:put_chars(S);
+ {error, beam_lib, _} ->
+ corrupter0(Term)
+ end
+ end;
corrupter(Term) ->
+ corrupter0(Term).
+
+corrupter0(Term) ->
?line try
S = io_lib:format("About to corrupt: ~P", [Term,12]),
io:put_chars(S)
diff --git a/erts/emulator/test/save_calls_SUITE.erl b/erts/emulator/test/save_calls_SUITE.erl
index 390b49b604..26ac4f2f7f 100644
--- a/erts/emulator/test/save_calls_SUITE.erl
+++ b/erts/emulator/test/save_calls_SUITE.erl
@@ -21,8 +21,10 @@
-include_lib("test_server/include/test_server.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0,groups/0,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2]).
-export([save_calls_1/1,dont_break_reductions/1]).
@@ -48,6 +50,27 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(dont_break_reductions,Config) ->
+ %% Skip on --enable-native-libs as hipe rescedules after each
+ %% function call.
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ Config;
+ Architecture ->
+ {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
+ case NativeChunk of
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
+ {skip,"Does not work for --enable-native-libs"};
+ {error, beam_lib, _} -> Config
+ end
+ end;
+init_per_testcase(_,Config) ->
+ Config.
+
+end_per_testcase(_,_Config) ->
+ ok.
dont_break_reductions(suite) ->
[];
diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl
index 98f1cf1ad5..71186d4942 100644
--- a/erts/emulator/test/smoke_test_SUITE.erl
+++ b/erts/emulator/test/smoke_test_SUITE.erl
@@ -51,7 +51,17 @@ end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(boot_combo = Case, Config) when is_list(Config) ->
+ case erlang:system_info(build_type) of
+ opt ->
+ init_per_tc(Case, Config);
+ _ ->
+ {skip,"Cannot test boot_combo in special builds since beam.* may not exist"}
+ end;
init_per_testcase(Case, Config) when is_list(Config) ->
+ init_per_tc(Case, Config).
+
+init_per_tc(Case, Config) ->
Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
[{testcase, Case},{watchdog, Dog}|Config].
@@ -121,18 +131,19 @@ start_node(Config) ->
start_node(Config, "").
start_node(Config, Args) when is_list(Config) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line {A, B, C} = now(),
- ?line Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(?config(testcase, Config))
- ++ "-"
- ++ integer_to_list(A)
- ++ "-"
- ++ integer_to_list(B)
- ++ "-"
- ++ integer_to_list(C)),
- ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
+ Pa = filename:dirname(code:which(?MODULE)),
+ {A, B, C} = now(),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(?config(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(A)
+ ++ "-"
+ ++ integer_to_list(B)
+ ++ "-"
+ ++ integer_to_list(C)),
+ Opts = [{args, "-pa "++Pa++" "++Args}],
+ ?t:start_node(Name, slave, Opts).
stop_node(Node) ->
?t:stop_node(Node).
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 8fe2402ca8..16a949c2a6 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -1,4 +1,4 @@
-#!/usr/bin/env perl
+#!/usr/bin/env perl -W
#
# %CopyrightBegin%
#
@@ -362,7 +362,7 @@ while (<>) {
$gen_to_spec{"$name/$arity"} = undef;
$num_specific{"$name/$arity"} = 0;
$min_window{"$name/$arity"} = 255;
- $obsolete[$op_num] = $obsolete eq '-';
+ $obsolete[$op_num] = defined $obsolete;
} else { # Unnumbered generic operation.
push(@unnumbered_generic, [$name, $arity]);
$unnumbered{$name,$arity} = 1;
@@ -379,7 +379,7 @@ while (<>) {
if @args > $max_spec_operands;
&syntax_check($name, @args);
my $arity = @args;
- if ($obsolete[$gen_opnum{$name,$arity}]) {
+ if (defined $gen_opnum{$name,$arity} and $obsolete[$gen_opnum{$name,$arity}]) {
error("specific instructions may not be specified for obsolete instructions");
}
push(@{$specific_op{"$name/$arity"}}, [$name, $hot, @args]);
@@ -810,8 +810,8 @@ sub compiler_output {
#
# Generate .hrl file.
#
- my($name) = "$outdir/${module}.hrl";
- open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
+ my($hrl_name) = "$outdir/${module}.hrl";
+ open(STDOUT, ">$hrl_name") || die "Failed to open $hrl_name for writing: $!\n";
&comment('erlang');
for ($i = 0; $i < @tag_type && $i < 8; $i++) {
@@ -1251,8 +1251,8 @@ sub compile_transform {
$arity++ unless $list[1] eq '*';
$_ = [ @list ];
}
-
- if ($obsolete[$gen_opnum{$name,$arity}]) {
+
+ if (defined $gen_opnum{$name,$arity} && $obsolete[$gen_opnum{$name,$arity}]) {
error("obsolete function must not be used in transformations");
}
@@ -1704,14 +1704,15 @@ sub tr_gen_to {
#
my($first_ref) = shift(@code);
my($size, $first, $key) = @$first_ref;
- my($dummy, $op, $arity) = @$first;
+ my($dummy, $arity);
+ ($dummy, $op, $arity) = @$first;
my($comment) = "\n/*\n * Line $line:\n * $orig_transform\n */\n\n";
$min_window{$key} = $min_window
if $min_window{$key} > $min_window;
my $prev_last;
$prev_last = pop(@{$gen_transform{$key}})
- if defined @{$gen_transform{$key}}; # Fail
+ if defined $gen_transform{$key}; # Fail
if ($prev_last && !is_instr($prev_last, 'fail')) {
error("Line $line: A previous transformation shadows '$orig_transform'");
@@ -1719,7 +1720,7 @@ sub tr_gen_to {
unless ($cannot_fail) {
unshift(@code, make_op('', 'try_me_else',
tr_code_len(@code)));
- push(@code, make_op(""), make_op("$key", 'fail'));
+ push(@code, make_op("$key", 'fail'));
}
unshift(@code, make_op($comment));
push(@{$gen_transform{$key}}, @code),
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 2267f9b12b..3577abf6ba 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -64,7 +64,7 @@ int epmd_dbg(int level,int port) /* Utility to debug epmd... */
if(port)
{
argv[argc++] = "-port";
- sprintf(ibuff,"%d",port);
+ erts_snprintf(ibuff, sizeof(ibuff), "%d",port);
argv[argc++] = ibuff;
}
argv[argc] = NULL;
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index da575affa1..36565b7438 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -23,6 +23,7 @@
#endif
#include "epmd.h" /* Renamed from 'epmd_r4.h' */
#include "epmd_int.h"
+#include "erl_printf.h" /* erts_snprintf */
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
@@ -633,7 +634,7 @@ static void do_request(g, fd, s, buf, bsize)
/* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
change in syntax will break < OTP R3A */
- sprintf(wbuf,"name %s at port %d\n",node->symname, node->port);
+ erts_snprintf(wbuf, sizeof(wbuf), "name %s at port %d\n",node->symname, node->port);
len = strlen(wbuf);
if (reply(g, fd, wbuf, len) != len)
{
@@ -669,7 +670,7 @@ static void do_request(g, fd, s, buf, bsize)
/* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
change in syntax will break < OTP R3A */
- sprintf(wbuf,"active name <%s> at port %d, fd = %d\n",
+ erts_snprintf(wbuf, sizeof(wbuf), "active name <%s> at port %d, fd = %d\n",
node->symname, node->port, node->fd);
len = strlen(wbuf) + 1;
if (reply(g, fd,wbuf,len) != len)
@@ -686,7 +687,7 @@ static void do_request(g, fd, s, buf, bsize)
/* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
change in syntax will break < OTP R3A */
- sprintf(wbuf,"old/unused name <%s>, port = %d, fd = %d \n",
+ erts_snprintf(wbuf, sizeof(wbuf), "old/unused name <%s>, port = %d, fd = %d \n",
node->symname,node->port, node->fd);
len = strlen(wbuf) + 1;
if (reply(g, fd,wbuf,len) != len)
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 52add1c1ba..04d3425fe0 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -989,8 +989,7 @@ int main(int argc, char **argv)
if (print_args_exit) {
for (i = 1; i < EargsCnt; i++)
- printf("%s ", Eargsp[i]);
- printf("\n");
+ printf("%s\n", Eargsp[i]);
exit(0);
}
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 7b78cc489d..81d797dc7e 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -115,7 +115,8 @@
# endif
#endif
-#define HEART_COMMAND_ENV "HEART_COMMAND"
+#define HEART_COMMAND_ENV "HEART_COMMAND"
+#define ERL_CRASH_DUMP_SECONDS_ENV "ERL_CRASH_DUMP_SECONDS"
#define MSG_HDR_SIZE 2
#define MSG_HDR_PLUS_OP_SIZE 3
@@ -131,13 +132,14 @@ struct msg {
};
/* operations */
-#define HEART_ACK 1
-#define HEART_BEAT 2
-#define SHUT_DOWN 3
-#define SET_CMD 4
-#define CLEAR_CMD 5
-#define GET_CMD 6
-#define HEART_CMD 7
+#define HEART_ACK (1)
+#define HEART_BEAT (2)
+#define SHUT_DOWN (3)
+#define SET_CMD (4)
+#define CLEAR_CMD (5)
+#define GET_CMD (6)
+#define HEART_CMD (7)
+#define PREPARING_CRASH (8)
/* Maybe interesting to change */
@@ -165,10 +167,11 @@ unsigned long heart_beat_kill_pid = 0;
#define SOL_WD_TIMEOUT (heart_beat_timeout+heart_beat_boot_delay)
/* reasons for reboot */
-#define R_TIMEOUT 1
-#define R_CLOSED 2
-#define R_ERROR 3
-#define R_SHUT_DOWN 4
+#define R_TIMEOUT (1)
+#define R_CLOSED (2)
+#define R_ERROR (3)
+#define R_SHUT_DOWN (4)
+#define R_CRASHING (5) /* Doing a crash dump and we will wait for it */
/* macros */
@@ -178,8 +181,8 @@ unsigned long heart_beat_kill_pid = 0;
/* prototypes */
-static int message_loop(int,int);
-static void do_terminate(int);
+static int message_loop(int, int);
+static void do_terminate(int, int);
static int notify_ack(int);
static int heart_cmd_reply(int, char *);
static int write_message(int, struct msg *);
@@ -190,6 +193,7 @@ static void print_error(const char *,...);
static void debugf(const char *,...);
static void init_timestamp(void);
static time_t timestamp(time_t *);
+static int wait_until_close_write_or_env_tmo(int);
#ifdef __WIN32__
static BOOL enable_privilege(void);
@@ -328,12 +332,14 @@ static void get_arguments(int argc, char** argv) {
debugf("arguments -ht %d -wt %d -pid %lu\n",h,w,p);
}
-int
-main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
+
+ if (is_env_set("HEART_DEBUG")) {
+ fprintf(stderr, "heart: debug is ON!\r\n");
+ debug_on = 1;
+ }
+
get_arguments(argc,argv);
- if (is_env_set("HEART_DEBUG"))
- debug_on=1;
#ifdef __WIN32__
if (debug_on) {
if(!is_env_set("ERLSRV_SERVICE_NAME")) {
@@ -354,7 +360,7 @@ main(int argc, char **argv)
program_name[sizeof(program_name)-1] = '\0';
notify_ack(erlout_fd);
cmd[0] = '\0';
- do_terminate(message_loop(erlin_fd,erlout_fd));
+ do_terminate(erlin_fd,message_loop(erlin_fd,erlout_fd));
return 0;
}
@@ -388,6 +394,7 @@ message_loop(erlin_fd, erlout_fd)
#endif
while (1) {
+ /* REFACTOR: below to select/tmo function */
#ifdef __WIN32__
wresult = WaitForSingleObject(hevent_dataready,SELECT_TIMEOUT*1000+ 2);
if (wresult == WAIT_FAILED) {
@@ -482,6 +489,10 @@ message_loop(erlin_fd, erlout_fd)
free_env_val(env);
}
break;
+ case PREPARING_CRASH:
+ /* Erlang has reached a crushdump point (is crashing for sure) */
+ print_error("Erlang is crashing .. (waiting for crash dump file)");
+ return R_CRASHING;
default:
/* ignore all other messages */
break;
@@ -612,72 +623,130 @@ void win_system(char *command)
* do_terminate
*/
static void
-do_terminate(reason)
- int reason;
-{
+do_terminate(int erlin_fd, int reason) {
/*
When we get here, we have HEART_BEAT_BOOT_DELAY secs to finish
(plus heart_beat_report_delay if under VxWorks), so we don't need
to call wd_reset().
*/
-
+ int ret = 0, tmo=0;
+ char *tmo_env;
+
switch (reason) {
case R_SHUT_DOWN:
break;
+ case R_CRASHING:
+ if (is_env_set(ERL_CRASH_DUMP_SECONDS_ENV)) {
+ tmo_env = get_env(ERL_CRASH_DUMP_SECONDS_ENV);
+ tmo = atoi(tmo_env);
+ print_error("Waiting for dump - timeout set to %d seconds.", tmo);
+ wait_until_close_write_or_env_tmo(tmo);
+ free_env_val(tmo_env);
+ }
+ /* fall through */
case R_TIMEOUT:
- case R_ERROR:
case R_CLOSED:
+ case R_ERROR:
default:
-#if defined(__WIN32__)
{
- if(!cmd[0]) {
- char *command = get_env(HEART_COMMAND_ENV);
- if(!command)
- print_error("Would reboot. Terminating.");
- else {
- kill_old_erlang();
- /* High prio combined with system() works badly indeed... */
- SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
- win_system(command);
- print_error("Executed \"%s\". Terminating.",command);
+#if defined(__WIN32__) /* Not VxWorks */
+ if(!cmd[0]) {
+ char *command = get_env(HEART_COMMAND_ENV);
+ if(!command)
+ print_error("Would reboot. Terminating.");
+ else {
+ kill_old_erlang();
+ /* High prio combined with system() works badly indeed... */
+ SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ win_system(command);
+ print_error("Executed \"%s\". Terminating.",command);
+ }
+ free_env_val(command);
+ } else {
+ kill_old_erlang();
+ /* High prio combined with system() works badly indeed... */
+ SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ win_system(&cmd[0]);
+ print_error("Executed \"%s\". Terminating.",cmd);
}
- free_env_val(command);
- }
- else {
- kill_old_erlang();
- /* High prio combined with system() works badly indeed... */
- SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
- win_system(&cmd[0]);
- print_error("Executed \"%s\". Terminating.",cmd);
- }
- }
-
#else
- {
- if(!cmd[0]) {
- char *command = get_env(HEART_COMMAND_ENV);
- if(!command)
- print_error("Would reboot. Terminating.");
- else {
- kill_old_erlang();
- /* suppress gcc warning with 'if' */
- if(system(command));
- print_error("Executed \"%s\". Terminating.",command);
+ if(!cmd[0]) {
+ char *command = get_env(HEART_COMMAND_ENV);
+ if(!command)
+ print_error("Would reboot. Terminating.");
+ else {
+ kill_old_erlang();
+ /* suppress gcc warning with 'if' */
+ ret = system(command);
+ print_error("Executed \"%s\" -> %d. Terminating.",command, ret);
+ }
+ free_env_val(command);
+ } else {
+ kill_old_erlang();
+ /* suppress gcc warning with 'if' */
+ ret = system((char*)&cmd[0]);
+ print_error("Executed \"%s\" -> %d. Terminating.",cmd, ret);
}
- free_env_val(command);
- }
- else {
- kill_old_erlang();
- /* suppress gcc warning with 'if' */
- if(system((char*)&cmd[0]));
- print_error("Executed \"%s\". Terminating.",cmd);
- }
+#endif
}
break;
-#endif
} /* switch(reason) */
}
+
+/* Waits until something happens on socket or handle
+ *
+ * Uses global variables erlin_fd or hevent_dataready
+ */
+int wait_until_close_write_or_env_tmo(int tmo) {
+ int i = 0;
+
+#ifdef __WIN32__
+ DWORD wresult;
+ DWORD wtmo = INFINITE;
+
+ if (tmo >= 0) {
+ wtmo = tmo*1000 + 2;
+ }
+
+ wresult = WaitForSingleObject(hevent_dataready, wtmo);
+ if (wresult == WAIT_FAILED) {
+ print_last_error();
+ return -1;
+ }
+
+ if (wresult == WAIT_TIMEOUT) {
+ debugf("wait timed out\n");
+ i = 0;
+ } else {
+ debugf("wait ok\n");
+ i = 1;
+ }
+#else
+ fd_set read_fds;
+ int max_fd;
+ struct timeval timeout;
+ struct timeval *tptr = NULL;
+
+ max_fd = erlin_fd; /* global */
+
+ if (tmo >= 0) {
+ timeout.tv_sec = tmo; /* On Linux timeout is modified by select */
+ timeout.tv_usec = 0;
+ tptr = &timeout;
+ }
+
+ FD_ZERO(&read_fds);
+ FD_SET(erlin_fd, &read_fds);
+ if ((i = select(max_fd + 1, &read_fds, NULLFDS, NULLFDS, tptr)) < 0) {
+ print_error("error in select.");
+ return -1;
+ }
+#endif
+ return i;
+}
+
+
/*
* notify_ack
*
@@ -868,12 +937,13 @@ debugf(const char *format,...)
{
va_list args;
- if (!debug_on) return;
- va_start(args, format);
- fprintf(stderr, "Heart: ");
- vfprintf(stderr, format, args);
- va_end(args);
- fprintf(stderr, "\r\n");
+ if (debug_on) {
+ va_start(args, format);
+ fprintf(stderr, "Heart: ");
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\r\n");
+ }
}
#ifdef __WIN32__
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index e923233ce9..b9a0e6bde3 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -2522,7 +2522,7 @@ static char *format_address(int siz, AddrByte *addr)
*buff='\0';
if (siz <= 4) {
while(siz--) {
- sprintf(tmp,"%d",(int) *addr++);
+ erts_snprintf(tmp, sizeof(tmp), "%d",(int) *addr++);
strcat(buff,tmp);
if(siz) {
strcat(buff,".");
@@ -2531,7 +2531,7 @@ static char *format_address(int siz, AddrByte *addr)
return buff;
}
while(siz--) {
- sprintf(tmp,"%02x",(int) *addr++);
+ erts_snprintf(tmp, sizeof(tmp), "%02x",(int) *addr++);
strcat(buff,tmp);
if(siz) {
strcat(buff,":");
@@ -2548,9 +2548,9 @@ static void debugf(char *format, ...)
va_start(ap,format);
#ifdef WIN32
- sprintf(buff,"%s[%d] (DEBUG):",program_name,(int) GetCurrentThreadId());
+ erts_snprintf(buff, sizeof(buff), "%s[%d] (DEBUG):",program_name,(int) GetCurrentThreadId());
#else
- sprintf(buff,"%s[%d] (DEBUG):",program_name,(int) getpid());
+ erts_snprintf(buff, sizeof(buff), "%s[%d] (DEBUG):",program_name,(int) getpid());
#endif
ptr = buff + strlen(buff);
erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
@@ -2574,7 +2574,7 @@ static void warning(char *format, ...)
va_list ap;
va_start(ap,format);
- sprintf(buff,"%s[%d]: WARNING:",program_name, (int) getpid());
+ erts_snprintf(buff, sizeof(buff), "%s[%d]: WARNING:",program_name, (int) getpid());
ptr = buff + strlen(buff);
erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
strcat(ptr,"\r\n");
@@ -2597,7 +2597,7 @@ static void fatal(char *format, ...)
va_list ap;
va_start(ap,format);
- sprintf(buff,"%s[%d]: FATAL ERROR:",program_name, (int) getpid());
+ erts_snprintf(buff, sizeof(buff), "%s[%d]: FATAL ERROR:",program_name, (int) getpid());
ptr = buff + strlen(buff);
erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
strcat(ptr,"\r\n");
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index e0d7404de7..651452e531 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -267,11 +267,16 @@ if [ "x$GDB" = "x" ]; then
valgrind_misc_flags="$VALGRIND_MISC_FLAGS"
fi
beam_args=`$EXEC -emu_args_exit ${1+"$@"}`
- # Ahhhh... Need to quote $PROGNAME...
- early_beam_args=`echo $beam_args | sed "s|^\(.*-progname\).*$|\1|g"`
- late_beam_args=`echo $beam_args | sed "s|^$pre_beam_args.*\(-- -home.*\)$|\1|g"`
-
- exec valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $emu_xargs $early_beam_args "$PROGNAME" $late_beam_args -pz $PRELOADED
+
+ # Time for some argument passing voodoo:
+ # $beam_args is a list of command line arguments separated by newlines.
+ # Make "$@" represent those arguments verbatim (including spaces and quotes).
+ SAVE_IFS="$IFS"
+ IFS='
+'
+ set -- $beam_args
+ IFS="$SAVE_IFS"
+ exec valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $emu_xargs "$@" -pz $PRELOADED
else
exec $EXEC $eeargs $xargs ${1+"$@"}
fi
diff --git a/erts/etc/win32/nsis/Makefile b/erts/etc/win32/nsis/Makefile
index f377a68c69..a53ac708f8 100644
--- a/erts/etc/win32/nsis/Makefile
+++ b/erts/etc/win32/nsis/Makefile
@@ -91,7 +91,7 @@ release_spec:
fi;\
if [ '!' -z "$(REDIST_FILE)" -a '!' -z "$(REDIST_DLL_VERSION)" ];\
then \
- cp $(REDIST_FILE) "$(RELEASE_PATH)/$(REDIST_TARGET);"\
+ cp $(REDIST_FILE) "$(RELEASE_PATH)/$(REDIST_TARGET)";\
echo '!define HAVE_REDIST_FILE 1' >> $(VERSION_HEADER); \
echo '!define REDIST_DLL_VERSION "$(REDIST_DLL_VERSION)"' >> $(VERSION_HEADER);\
echo '!define REDIST_DLL_NAME "$(REDIST_DLL_NAME)"' >> $(VERSION_HEADER);\
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 142c26c0ca..e1885c627a 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -355,10 +355,8 @@ extern ethr_runtime_t ethr_runtime__;
# include "sparc64/ethread.h"
# endif
# endif
-#if 0
# include "gcc/ethread.h"
# include "libatomic_ops/ethread.h"
-#endif
# endif
# elif defined(ETHR_HAVE_LIBATOMIC_OPS)
# include "libatomic_ops/ethread.h"
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index 5f28f22606..b7ceb0a3fd 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -84,13 +84,14 @@ undefined_functions(Config) when is_list(Config) ->
"ExcludedFrom = ~p:_/_,"
"Undef - Undef | ExcludedFrom",
[UndefS,ExcludeFrom]),
- ?line {ok,Undef0} = xref:q(Server, lists:flatten(Q)),
- ?line Undef1 = hipe_filter(Undef0),
- ?line Undef2 = ssl_crypto_filter(Undef1),
- ?line Undef3 = edoc_filter(Undef2),
+ {ok,Undef0} = xref:q(Server, lists:flatten(Q)),
+ Undef1 = hipe_filter(Undef0),
+ Undef2 = ssl_crypto_filter(Undef1),
+ Undef3 = edoc_filter(Undef2),
Undef4 = eunit_filter(Undef3),
Undef5 = dialyzer_filter(Undef4),
- Undef = wx_filter(Undef5),
+ Undef6 = wx_filter(Undef5),
+ Undef = gs_filter(Undef6),
case Undef of
[] -> ok;
@@ -202,6 +203,16 @@ wx_filter(Undef) ->
_ -> Undef
end.
+gs_filter(Undef) ->
+ case code:lib_dir(gs) of
+ {error,bad_name} ->
+ filter(fun({_,{gs,_,_}}) -> false;
+ ({_,{gse,_,_}}) -> false;
+ ({_,{tool_utils,_,_}}) -> false;
+ (_) -> true
+ end, Undef);
+ _ -> Undef
+ end.
deprecated_not_in_obsolete(Config) when is_list(Config) ->
?line Server = ?config(xref_server, Config),