aboutsummaryrefslogtreecommitdiffstats
path: root/erts/etc/common
diff options
context:
space:
mode:
Diffstat (limited to 'erts/etc/common')
-rw-r--r--erts/etc/common/Makefile.in136
-rw-r--r--erts/etc/common/dialyzer.c14
-rw-r--r--erts/etc/common/erlc.c12
-rw-r--r--erts/etc/common/erlexec.c221
-rw-r--r--erts/etc/common/heart.c325
-rw-r--r--erts/etc/common/inet_gethost.c12
6 files changed, 386 insertions, 334 deletions
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 28c5e5ccad..ea70946346 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -33,11 +33,7 @@ else
ifeq ($(TYPE),purify)
PURIFY = purify
TYPEMARKER =
-ifeq ($(findstring ose,$(TARGET)),ose)
-TYPE_FLAGS = -g -XO -DPURIFY
-else
TYPE_FLAGS = -g -O2 -DPURIFY
-endif
else
override TYPE=opt
@@ -64,6 +60,9 @@ LD = @LD@
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@
+# For clock_gettime in heart
+RTLIBS = @LIBRT@
+
ifeq ($(TARGET),win32)
ifeq ($(TYPE),debug)
CFLAGS = $(subst -O2,-g,@CFLAGS@ @DEFS@ $(TYPE_FLAGS) @WFLAGS@ -I$(SYSDIR) \
@@ -77,25 +76,15 @@ EMUDIR = $(ERL_TOP)/erts/emulator/beam
EMUOSDIR = $(ERL_TOP)/erts/emulator/@ERLANG_OSTYPE@
SYSDIR = $(ERL_TOP)/erts/emulator/sys/@ERLANG_OSTYPE@
DRVDIR = $(ERL_TOP)/erts/emulator/drivers/@ERLANG_OSTYPE@
-VXETC = ../vxworks
UXETC = ../unix
OSEETC = ../ose
WINETC = ../win32
-ifeq ($(findstring vxworks,$(TARGET)), vxworks)
-ERLEXEC = erl.exec
-else
-ifeq ($(findstring ose,$(TARGET)), ose)
-ERLEXEC =
-TAR = @TAR@
-else
ifeq ($(TARGET), win32)
ERLEXEC = erlexec.dll
else
ERLEXEC = erlexec
endif
-endif
-endif
# On windows we always need reentrant libraries.
ifeq ($(TARGET),win32)
@@ -110,42 +99,6 @@ ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
# Release directory specification
# ----------------------------------------------------
-ifeq ($(findstring vxworks,$(TARGET)), vxworks)
-INSTALL_EMBEDDED_PROGS = $(BINDIR)/erl_io $(BINDIR)/rdate $(BINDIR)/vxcall
-INSTALL_EMBEDDED_DATA = $(BINDIR)/erl_script.sam $(VXETC)/resolv.conf
-INSTALL_INCLUDES = $(VXETC)/reclaim.h
-INSTALL_TOP = $(VXETC)/README.VxWorks
-INSTALL_MISC =
-INSTALL_SRC = heart.c $(VXETC)/heart_config.h $(VXETC)/heart_config.c \
- $(VXETC)/erl.exec.c $(VXETC)/rdate.c $(VXETC)/vxcall.c \
- $(VXETC)/erl_io.c
-ERLEXECDIR = $(VXETC)
-INSTALL_LIBS = $(OBJDIR)/reclaim.o
-INSTALL_OBJS = $(OBJDIR)/heart.o
-TEXTFILES = $(BINDIR)/erl_script.sam
-ERLSRV_OBJECTS=
-MC_OUTPUTS=
-ENTRY_LDFLAGS=
-ENTRY_OBJ=
-INSTALL_PROGS = \
- $(INET_GETHOST) \
- $(BINDIR)/heart \
- $(BINDIR)/$(ERLEXEC) \
- $(INSTALL_EMBEDDED_PROGS)
-else
-ifeq ($(findstring ose,$(TARGET)), ose)
-INSTALL_TOP = $(OSEETC)/README.OSE
-INSTALL_ERL_OSE = monolith lm erl_utils drivers port_progs host
-INSTALL_SRC =
-INSTALL_LIBS =
-INSTALL_OBJS =
-INSTALL_INCLUDES =
-INSTALL_PROGS =
-ERLSRV_OBJECTS=
-MC_OUTPUTS=
-ENTRY_LDFLAGS=
-ENTRY_OBJ=
-else
ifeq ($(TARGET),win32)
CFLAGS += -I$(EMUOSDIR) -I$(WINETC)
RC=rc.sh
@@ -207,7 +160,7 @@ endif
PORT_ENTRY_POINT=erl_port_entry
ENTRY_LDFLAGS=-entry:$(PORT_ENTRY_POINT)
-else
+else # UNIX (!win32)
ENTRY_LDFLAGS=
ENTRY_OBJ=
ERLSRV_OBJECTS=
@@ -232,8 +185,6 @@ INSTALL_PROGS = \
$(BINDIR)/$(ERLEXEC) \
$(INSTALL_EMBEDDED_PROGS)
endif
-endif
-endif
.PHONY: etc
etc: $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN)
@@ -396,56 +347,13 @@ endif
# End of windows specific targets.
#---------------------------------------------------------
-ifeq ($(findstring vxworks,$(TARGET)), vxworks)
-$(BINDIR)/heart: $(OBJDIR)/heart.o $(OBJDIR)/heart_config.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/heart.o $(OBJDIR)/heart_config.o
-
-$(OBJDIR)/heart_config.o: $(VXETC)/heart_config.c
- $(CC) $(CFLAGS) -o $@ -c $(VXETC)/heart_config.c
-
-$(OBJDIR)/reclaim.o: $(VXETC)/reclaim.c
- $(CC) $(CFLAGS) -o $@ -c $(VXETC)/reclaim.c
-
-$(OBJDIR)/heart.o: heart.c
- $(CC) $(CFLAGS) -I$(VXETC) -o $@ -c heart.c
-
-$(BINDIR)/erl_script.sam: $(VXETC)/erl_script.sam.in ../../vsn.mk
- sed -e 's;%VSN%;$(VSN);' \
- $(VXETC)/erl_script.sam.in > $(BINDIR)/erl_script.sam
-else
-
$(BINDIR)/heart@EXEEXT@: $(OBJDIR)/heart.o $(ENTRY_OBJ)
$(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/heart.o \
- $(ENTRY_OBJ) $(WINDSOCK)
+ $(RTLIBS) $(ENTRY_OBJ) $(WINDSOCK)
$(OBJDIR)/heart.o: heart.c $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c heart.c
-endif
-
-
-# VxWorks specific executables and objects ...
-
-$(BINDIR)/erl_io: $(OBJDIR)/erl_io.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erl_io.o
-
-$(OBJDIR)/erl_io.o: $(VXETC)/erl_io.c
- $(CC) $(CFLAGS) -o $@ -c $(VXETC)/erl_io.c
-
-$(BINDIR)/rdate: $(OBJDIR)/rdate.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/rdate.o
-
-$(OBJDIR)/rdate.o: $(VXETC)/rdate.c
- $(CC) $(CFLAGS) -o $@ -c $(VXETC)/rdate.c
-
-$(BINDIR)/vxcall: $(OBJDIR)/vxcall.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/vxcall.o
-
-$(OBJDIR)/vxcall.o: $(VXETC)/vxcall.c
- $(CC) $(CFLAGS) -o $@ -c $(VXETC)/vxcall.c
-
-
-
#
# Objects & executables
#
@@ -545,48 +453,48 @@ include $(ERL_TOP)/make/otp_release_targets.mk
.PHONY: release_spec
release_spec: etc
ifneq ($(INSTALL_OBJS),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/obj
- $(INSTALL_DATA) $(INSTALL_OBJS) $(RELEASE_PATH)/erts-$(VSN)/obj
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/obj"
+ $(INSTALL_DATA) $(INSTALL_OBJS) "$(RELEASE_PATH)/erts-$(VSN)/obj"
endif
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/bin"
ifneq ($(TARGET), win32)
ifneq ($(findstring vxworks,$(TARGET)), vxworks)
ifneq ($(findstring ose,$(TARGET)), ose)
- $(INSTALL_SCRIPT) erl.src $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_SCRIPT) erl.src "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
endif
endif
ifneq ($(INSTALL_PROGS),)
- $(INSTALL_PROGRAM) $(INSTALL_PROGS) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_TOP),)
- $(INSTALL_SCRIPT) $(INSTALL_TOP) $(RELEASE_PATH)
+ $(INSTALL_SCRIPT) $(INSTALL_TOP) "$(RELEASE_PATH)"
endif
ifneq ($(INSTALL_TOP_BIN),)
- $(INSTALL_PROGRAM) $(INSTALL_TOP_BIN) $(RELEASE_PATH)
+ $(INSTALL_PROGRAM) $(INSTALL_TOP_BIN) "$(RELEASE_PATH)"
endif
ifneq ($(INSTALL_MISC),)
- $(INSTALL_DIR) $(RELEASE_PATH)/misc
- $(INSTALL_SCRIPT) $(INSTALL_MISC) $(RELEASE_PATH)/misc
+ $(INSTALL_DIR) "$(RELEASE_PATH)/misc"
+ $(INSTALL_SCRIPT) $(INSTALL_MISC) "$(RELEASE_PATH)/misc"
endif
ifneq ($(INSTALL_ERL_OSE),)
- $(INSTALL_DIR) $(RELEASE_PATH)/build_erl_ose
+ $(INSTALL_DIR) "$(RELEASE_PATH)/build_erl_ose"
cd $(OSEETC) && $(TAR) erl_ose_$(SYSTEM_VSN).tar $(INSTALL_ERL_OSE)
- cd $(OSEETC) && $(INSTALL_SCRIPT) erl_ose_$(SYSTEM_VSN).tar $(RELEASE_PATH)/build_erl_ose
+ cd $(OSEETC) && $(INSTALL_SCRIPT) erl_ose_$(SYSTEM_VSN).tar "$(RELEASE_PATH)/build_erl_ose"
endif
ifneq ($(INSTALL_SRC),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/src
- $(INSTALL_DATA) $(INSTALL_SRC) $(RELEASE_PATH)/erts-$(VSN)/src
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/src"
+ $(INSTALL_DATA) $(INSTALL_SRC) "$(RELEASE_PATH)/erts-$(VSN)/src"
endif
ifneq ($(INSTALL_EMBEDDED_DATA),)
- $(INSTALL_DATA) $(INSTALL_EMBEDDED_DATA) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DATA) $(INSTALL_EMBEDDED_DATA) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_LIBS),)
- $(INSTALL_DATA) $(INSTALL_LIBS) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DATA) $(INSTALL_LIBS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_INCLUDES),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/include
- $(INSTALL_DATA) $(INSTALL_INCLUDES) $(RELEASE_PATH)/erts-$(VSN)/include
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/include"
+ $(INSTALL_DATA) $(INSTALL_INCLUDES) "$(RELEASE_PATH)/erts-$(VSN)/include"
endif
.PHONY: release_docs_spec
diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c
index 04e9199ef3..b8a7a2bf03 100644
--- a/erts/etc/common/dialyzer.c
+++ b/erts/etc/common/dialyzer.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2012. 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
@@ -189,6 +189,18 @@ main(int argc, char** argv)
argc--, argv++;
}
+ if (argc > 2 && strcmp(argv[1], "+P") == 0) {
+ PUSH2("+P", argv[2]);
+ argc--, argv++;
+ argc--, argv++;
+ } else PUSH2("+P", "1000000");
+
+ if (argc > 2 && strcmp(argv[1], "+sbt") == 0) {
+ PUSH2("+sbt", argv[2]);
+ argc--, argv++;
+ argc--, argv++;
+ }
+
PUSH("+B");
PUSH2("-boot", "start_clean");
PUSH3("-run", "dialyzer", "plain_cl");
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index 23f009ff4d..f63ba3ee64 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. 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
@@ -252,13 +252,6 @@ main(int argc, char** argv)
}
}
break;
- case 'h':
- if (strcmp(argv[1], "-hybrid") == 0) {
- UNSHIFT(argv[1]);
- } else {
- usage();
- }
- break;
case 'I':
PUSH2("@i", process_opt(&argc, &argv, 0));
break;
@@ -342,7 +335,7 @@ main(int argc, char** argv)
/* Push the following options:
* o makedep_phony
*/
- buf = strsave("makedep_add_missing");
+ buf = strsave("makedep_phony");
PUSH2("@option", buf);
break;
default:
@@ -649,7 +642,6 @@ usage(void)
{"-d", "turn on debugging of erlc itself"},
{"-Dname", "define name"},
{"-Dname=value", "define name to have value"},
- {"-hybrid", "compile using hybrid-heap emulator"},
{"-help", "shows this help text"},
{"-I path", "where to search for include files"},
{"-M", "generate a rule for make(1) describing the dependencies"},
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 29e423d363..50c61f50eb 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. 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
@@ -121,9 +121,11 @@ static char *plusM_other_switches[] = {
/* +s arguments with values */
static char *pluss_val_switches[] = {
"bt",
+ "bwt",
"cl",
"ct",
"wt",
+ "ws",
"ss",
"pp",
NULL
@@ -158,20 +160,13 @@ static char *plusz_val_switches[] = {
#endif
#define SMP_SUFFIX ".smp"
-#define HYBRID_SUFFIX ".hybrid"
-
-#ifdef __WIN32__
#define DEBUG_SUFFIX ".debug"
-#define EMU_TYPE_SUFFIX_LENGTH (strlen(HYBRID_SUFFIX)+(strlen(DEBUG_SUFFIX)))
-#else
-/* The length of the longest memory architecture suffix. */
-#define EMU_TYPE_SUFFIX_LENGTH strlen(HYBRID_SUFFIX)
-#endif
+#define EMU_TYPE_SUFFIX_LENGTH strlen(DEBUG_SUFFIX)
+
/*
* Define flags for different memory architectures.
*/
#define EMU_TYPE_SMP 0x0001
-#define EMU_TYPE_HYBRID 0x0002
#ifdef __WIN32__
#define EMU_TYPE_DEBUG 0x0004
@@ -185,7 +180,7 @@ void error(char* format, ...);
* Local functions.
*/
-#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_HYBRID_EMU)
+#if !defined(ERTS_HAVE_SMP_EMU)
static void usage_notsup(const char *switchname);
#endif
static void usage_msg(const char *msg);
@@ -251,7 +246,9 @@ static char* config_script = NULL; /* used by option -start_erl and -config */
static HANDLE this_module_handle;
static int run_werl;
-
+static WCHAR *utf8_to_utf16(unsigned char *bytes);
+static char *utf16_to_utf8(WCHAR *wstr);
+static WCHAR *latin1_to_utf16(char *str);
#endif
/*
@@ -269,8 +266,12 @@ static void
set_env(char *key, char *value)
{
#ifdef __WIN32__
- if (!SetEnvironmentVariable((LPCTSTR) key, (LPCTSTR) value))
+ WCHAR *wkey = latin1_to_utf16(key);
+ WCHAR *wvalue = utf8_to_utf16(value);
+ if (!SetEnvironmentVariableW(wkey, wvalue))
error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value);
+ efree(wkey);
+ efree(wvalue);
#else
size_t size = strlen(key) + 1 + strlen(value) + 1;
char *str = emalloc(size);
@@ -283,25 +284,33 @@ set_env(char *key, char *value)
#endif
}
+
static char *
get_env(char *key)
{
#ifdef __WIN32__
DWORD size = 32;
- char *value = NULL;
+ WCHAR *value = NULL;
+ WCHAR *wkey = latin1_to_utf16(key);
+ char *res;
while (1) {
DWORD nsz;
if (value)
efree(value);
- value = emalloc(size);
+ value = emalloc(size*sizeof(WCHAR));
SetLastError(0);
- nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size);
+ nsz = GetEnvironmentVariableW(wkey, value, size);
if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
efree(value);
+ efree(wkey);
return NULL;
}
- if (nsz <= size)
- return value;
+ if (nsz <= size) {
+ efree(wkey);
+ res = utf16_to_utf8(value);
+ efree(value);
+ return res;
+ }
size = nsz;
}
#else
@@ -368,9 +377,6 @@ add_extra_suffixes(char *prog, int type)
if (type == EMU_TYPE_SMP) {
p = write_str(p, SMP_SUFFIX);
}
- else if (type == EMU_TYPE_HYBRID) {
- p = write_str(p, HYBRID_SUFFIX);
- }
#ifdef __WIN32__
if (dll) {
p = write_str(p, DLL_EXT);
@@ -536,13 +542,6 @@ int main(int argc, char **argv)
emu_type_passed |= EMU_TYPE_DEBUG;
emu_type |= EMU_TYPE_DEBUG;
#endif
- } else if (strcmp(argv[i], "-hybrid") == 0) {
- emu_type_passed |= EMU_TYPE_HYBRID;
-#ifdef ERTS_HAVE_HYBRID_EMU
- emu_type |= EMU_TYPE_HYBRID;
-#else
- usage_notsup("-hybrid");
-#endif
} else if (strcmp(argv[i], "-extra") == 0) {
break;
}
@@ -553,19 +552,6 @@ int main(int argc, char **argv)
erts_cpu_info_destroy(cpuinfo);
cpuinfo = NULL;
- if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
- /*
- * We have a conflict. Only using explicitly passed arguments
- * may solve it...
- */
- emu_type &= emu_type_passed;
- if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
- usage_msg("Hybrid heap emulator with SMP support selected. The "
- "combination hybrid heap and SMP support is currently "
- "not supported.");
- }
- }
-
if (malloc_lib) {
if (strcmp(malloc_lib, "libc") != 0)
usage("+MYm");
@@ -1006,8 +992,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);
}
@@ -1118,9 +1103,6 @@ usage_aux(void)
"]"
#endif
"] "
-#ifdef ERTS_HAVE_HYBRID_EMU
- "[-hybrid] "
-#endif
"[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
"[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] "
"[+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
@@ -1139,7 +1121,7 @@ usage(const char *switchname)
usage_aux();
}
-#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_HYBRID_EMU)
+#if !defined(ERTS_HAVE_SMP_EMU)
static void
usage_notsup(const char *switchname)
{
@@ -1180,7 +1162,7 @@ start_epmd(char *epmd)
erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd", bindir);
arg1 = "-daemon";
#else
- erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd -daemon", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "\"%s" DIRSEP "epmd\" -daemon", bindir);
#endif
}
#ifdef __WIN32__
@@ -2115,4 +2097,147 @@ possibly_quote(char* arg)
return narg;
}
+/*
+ * Unicode helpers to handle environment and command line parameters on
+ * Windows. We internally handle all environment variables in UTF8,
+ * but put and get the environment using the WCHAR (limited UTF16) interface
+ *
+ * These are simplified to only handle Unicode characters that can fit in
+ * Windows simplified UTF16, i.e. characters that fit in 16 bits.
+ */
+
+static int utf8_len(unsigned char first)
+{
+ if ((first & ((unsigned char) 0x80)) == 0) {
+ return 1;
+ } else if ((first & ((unsigned char) 0xE0)) == 0xC0) {
+ return 2;
+ } else if ((first & ((unsigned char) 0xF0)) == 0xE0) {
+ return 3;
+ } else if ((first & ((unsigned char) 0xF8)) == 0xF0) {
+ return 4;
+ }
+ return 1; /* will be a '?' */
+}
+
+static WCHAR *utf8_to_utf16(unsigned char *bytes)
+{
+ unsigned int unipoint;
+ unsigned char *tmp = bytes;
+ WCHAR *target, *res;
+ int num = 0;
+
+ while (*tmp) {
+ num++;
+ tmp += utf8_len(*tmp);
+ }
+ res = target = emalloc((num + 1) * sizeof(WCHAR));
+ while (*bytes) {
+ if (((*bytes) & ((unsigned char) 0x80)) == 0) {
+ unipoint = (Uint) *bytes;
+ ++bytes;
+ } else if (((*bytes) & ((unsigned char) 0xE0)) == 0xC0) {
+ unipoint =
+ (((Uint) ((*bytes) & ((unsigned char) 0x1F))) << 6) |
+ ((Uint) (bytes[1] & ((unsigned char) 0x3F)));
+ bytes += 2;
+ } else if (((*bytes) & ((unsigned char) 0xF0)) == 0xE0) {
+ unipoint =
+ (((Uint) ((*bytes) & ((unsigned char) 0xF))) << 12) |
+ (((Uint) (bytes[1] & ((unsigned char) 0x3F))) << 6) |
+ ((Uint) (bytes[2] & ((unsigned char) 0x3F)));
+ if (unipoint > 0xFFFF) {
+ unipoint = (unsigned int) '?';
+ }
+ bytes +=3;
+ } else if (((*bytes) & ((unsigned char) 0xF8)) == 0xF0) {
+ unipoint = (unsigned int) '?'; /* Cannot put in a wchar */
+ bytes += 4;
+ } else {
+ unipoint = (unsigned int) '?';
+ }
+ *target++ = (WCHAR) unipoint;
+ }
+ *target = L'\0';
+ return res;
+}
+
+static int put_utf8(WCHAR ch, unsigned char *target, int sz, int *pos)
+{
+ Uint x = (Uint) ch;
+ if (x < 0x80) {
+ if (*pos >= sz) {
+ return -1;
+ }
+ target[(*pos)++] = (unsigned char) x;
+ }
+ else if (x < 0x800) {
+ if (((*pos) + 1) >= sz) {
+ return -1;
+ }
+ target[(*pos)++] = (((unsigned char) (x >> 6)) |
+ ((unsigned char) 0xC0));
+ target[(*pos)++] = (((unsigned char) (x & 0x3F)) |
+ ((unsigned char) 0x80));
+ } else {
+ if ((x >= 0xD800 && x <= 0xDFFF) ||
+ (x == 0xFFFE) ||
+ (x == 0xFFFF)) { /* Invalid unicode range */
+ return -1;
+ }
+ if (((*pos) + 2) >= sz) {
+ return -1;
+ }
+
+ target[(*pos)++] = (((unsigned char) (x >> 12)) |
+ ((unsigned char) 0xE0));
+ target[(*pos)++] = ((((unsigned char) (x >> 6)) & 0x3F) |
+ ((unsigned char) 0x80));
+ target[(*pos)++] = (((unsigned char) (x & 0x3F)) |
+ ((unsigned char) 0x80));
+ }
+ return 0;
+}
+
+static int need_bytes_for_utf8(WCHAR x)
+{
+ if (x < 0x80)
+ return 1;
+ else if (x < 0x800)
+ return 2;
+ else
+ return 3;
+}
+
+static WCHAR *latin1_to_utf16(char *str)
+{
+ int len = strlen(str);
+ int i;
+ WCHAR *wstr = emalloc((len+1) * sizeof(WCHAR));
+ for(i=0;i<len;++i)
+ wstr[i] = (WCHAR) str[i];
+ wstr[len] = L'\0';
+ return wstr;
+}
+
+static char *utf16_to_utf8(WCHAR *wstr)
+{
+ int len = wcslen(wstr);
+ char *result;
+ int i,pos;
+ int reslen = 0;
+ for(i=0;i<len;++i) {
+ reslen += need_bytes_for_utf8(wstr[i]);
+ }
+ result = emalloc(reslen+1);
+ pos = 0;
+ for(i=0;i<len;++i) {
+ if (put_utf8((int) wstr[i], result, reslen, &pos) < 0) {
+ break;
+ }
+ }
+ result[pos] = '\0';
+ return result;
+}
+
#endif
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 755e308219..81d797dc7e 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -66,8 +66,7 @@
* input and output file descriptors (0 and 1). These descriptors
* (and the standard error descriptor 2) must NOT be closed
* explicitely by this program at termination (in UNIX it is
- * taken care of by the operating system itself; in VxWorks
- * it is taken care of by the spawn driver part of the Emulator).
+ * taken care of by the operating system itself).
*
* END OF FILE
*
@@ -75,12 +74,6 @@
* that there is no process at the other end of the connection
* having the connection open for writing (end-of-file).
*
- * HARDWARE WATCHDOG
- *
- * When used with VxWorks(with CPU40), the hardware
- * watchdog is enabled, making sure that the system reboots
- * even if the heart port program malfunctions or the system
- * is completely overloaded.
*/
#ifdef HAVE_CONFIG_H
@@ -93,18 +86,12 @@
#include <fcntl.h>
#include <process.h>
#endif
-#ifdef VXWORKS
-#include "sys.h"
-#endif
/*
* Implement time correction using times() call even on Linuxes
* that can simulate gethrtime with clock_gettime, no use implementing
* a phony gethrtime in this file as the time questions are so infrequent.
*/
-#if defined(CORRET_USING_TIMES) || defined(GETHRTIME_WITH_CLOCK_GETTIME)
-# define HEART_CORRECT_USING_TIMES 1
-#endif
#include <stdio.h>
#include <stddef.h>
@@ -116,31 +103,20 @@
#include <time.h>
#include <errno.h>
-#ifdef VXWORKS
-# include <vxWorks.h>
-# include <ioLib.h>
-# include <selectLib.h>
-# include <netinet/in.h>
-# include <rebootLib.h>
-# include <sysLib.h>
-# include <taskLib.h>
-# include <wdLib.h>
-# include <taskHookLib.h>
-# include <selectLib.h>
-#endif
-#if !defined(__WIN32__) && !defined(VXWORKS)
+#if !defined(__WIN32__)
# include <sys/types.h>
# include <netinet/in.h>
# include <sys/time.h>
# include <unistd.h>
# include <signal.h>
-# if defined(HEART_CORRECT_USING_TIMES)
+# if defined(CORRECT_USING_TIMES)
# include <sys/times.h>
# include <limits.h>
# 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
@@ -156,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 */
@@ -190,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 */
@@ -203,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 *);
@@ -215,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);
@@ -353,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")) {
@@ -379,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;
}
@@ -413,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) {
@@ -447,7 +429,8 @@ message_loop(erlin_fd, erlout_fd)
*/
timestamp(&now);
if (now > last_received + heart_beat_timeout) {
- print_error("heart-beat time-out.");
+ print_error("heart-beat time-out, no activity for %lu seconds",
+ (unsigned long) (now - last_received));
return R_TIMEOUT;
}
/*
@@ -506,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;
@@ -550,8 +537,7 @@ kill_old_erlang(void){
CloseHandle(erlh);
}
}
-#elif !defined(VXWORKS)
-/* Unix eh? */
+#else
static void
kill_old_erlang(void){
pid_t pid;
@@ -570,7 +556,7 @@ kill_old_erlang(void){
}
}
}
-#endif /* Not on VxWorks */
+#endif
#ifdef __WIN32__
void win_system(char *command)
@@ -637,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__) /* 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);
+#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
*
@@ -893,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__
@@ -1026,60 +1071,30 @@ time_t timestamp(time_t *res)
return r;
}
-#elif defined(VXWORKS)
-
-static WDOG_ID watchdog_id;
-static volatile unsigned elapsed;
-static WIND_TCB *this_task;
-/* A simple variable is enough to lock the time update, as the
- watchdog is run at interrupt level and never preempted. */
-static volatile int lock_time;
-
-static void my_delete_hook(WIND_TCB *tcb)
-{
- if (tcb == this_task) {
- wdDelete(watchdog_id);
- watchdog_id = NULL;
- taskDeleteHookDelete((FUNCPTR) &my_delete_hook);
- }
-}
+#elif defined(HAVE_GETHRTIME) || defined(GETHRTIME_WITH_CLOCK_GETTIME)
-static void my_wd_routine(int count)
-{
- if (watchdog_id != NULL) {
- ++count;
- if (!lock_time) {
- elapsed += count;
- count = 0;
- }
- wdStart(watchdog_id, sysClkRateGet(),
- (FUNCPTR) &my_wd_routine, count);
- }
-}
+#if defined(GETHRTIME_WITH_CLOCK_GETTIME)
+typedef long long SysHrTime;
-void init_timestamp(void)
-{
- lock_time = 0;
- elapsed = 0;
- watchdog_id = wdCreate();
- this_task = (WIND_TCB *) taskIdSelf();
- taskDeleteHookAdd((FUNCPTR) &my_delete_hook);
- wdStart(watchdog_id, sysClkRateGet(),
- (FUNCPTR) &my_wd_routine, 0);
-}
+SysHrTime sys_gethrtime(void);
-time_t timestamp(time_t *res)
+SysHrTime sys_gethrtime(void)
{
- time_t r;
- ++lock_time;
- r = (time_t) elapsed;
- --lock_time;
- if (res != NULL)
- *res = r;
- return r;
+ struct timespec ts;
+ long long result;
+ if (clock_gettime(CLOCK_MONOTONIC,&ts) != 0) {
+ print_error("Fatal, could not get clock_monotonic value, terminating! "
+ "errno = %d\n", errno);
+ exit(1);
+ }
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ return (SysHrTime) result;
}
-
-#elif defined(HAVE_GETHRTIME)
+#else
+typedef hrtime_t SysHrTime;
+#define sys_gethrtime() gethrtime()
+#endif
void init_timestamp(void)
{
@@ -1087,14 +1102,14 @@ void init_timestamp(void)
time_t timestamp(time_t *res)
{
- hrtime_t ht = gethrtime();
+ SysHrTime ht = sys_gethrtime();
time_t r = (time_t) (ht / 1000000000);
if (res != NULL)
*res = r;
return r;
}
-#elif defined(HEART_CORRECT_USING_TIMES)
+#elif defined(CORRECT_USING_TIMES)
# ifdef NO_SYSCONF
# include <sys/param.h>
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");