aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/Makefile.in8
-rw-r--r--erts/emulator/beam/erl_alloc.c7
-rw-r--r--erts/emulator/beam/erl_nif.c30
-rwxr-xr-x[-rw-r--r--]erts/emulator/drivers/win32/win_efile.c131
-rw-r--r--erts/emulator/sys/win32/sys.c116
-rw-r--r--erts/emulator/test/port_SUITE.erl24
-rw-r--r--erts/emulator/test/port_SUITE_data/dead_port.c6
-rw-r--r--erts/etc/common/Makefile.in14
-rw-r--r--erts/etc/common/ct_run.c (renamed from erts/etc/common/run_test.c)28
-rw-r--r--erts/etc/unix/Install.src5
-rw-r--r--erts/etc/win32/Install.c16
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/ld.sh2
12 files changed, 318 insertions, 69 deletions
diff --git a/erts/Makefile.in b/erts/Makefile.in
index dc8edcd928..2e63fc469e 100644
--- a/erts/Makefile.in
+++ b/erts/Makefile.in
@@ -87,17 +87,20 @@ endif
# in the same directory...
local_setup:
@cd start_scripts && $(MAKE)
+ @echo `ls $(ERL_TOP)/bin/`
@rm -f $(ERL_TOP)/bin/erl $(ERL_TOP)/bin/erlc $(ERL_TOP)/bin/cerl \
$(ERL_TOP)/bin/erl.exe $(ERL_TOP)/bin/erlc.exe \
$(ERL_TOP)/bin/escript $(ERL_TOP)/bin/escript.exe \
$(ERL_TOP)/bin/dialyzer $(ERL_TOP)/bin/dialyzer.exe \
$(ERL_TOP)/bin/typer $(ERL_TOP)/bin/typer.exe \
$(ERL_TOP)/bin/run_test $(ERL_TOP)/bin/run_test.exe \
+ $(ERL_TOP)/bin/ct_run $(ERL_TOP)/bin/ct_run.exe \
$(ERL_TOP)/bin/start*.boot $(ERL_TOP)/bin/start*.script
@if [ "X$(TARGET)" = "Xwin32" ]; then \
cp $(ERL_TOP)/bin/$(TARGET)/dialyzer.exe $(ERL_TOP)/bin/dialyzer.exe; \
cp $(ERL_TOP)/bin/$(TARGET)/typer.exe $(ERL_TOP)/bin/typer.exe; \
- cp $(ERL_TOP)/bin/$(TARGET)/run_test.exe $(ERL_TOP)/bin/run_test.exe; \
+ cp $(ERL_TOP)/bin/$(TARGET)/ct_run.exe $(ERL_TOP)/bin/ct_run.exe; \
+ cp $(ERL_TOP)/bin/$(TARGET)/ct_run.exe $(ERL_TOP)/bin/run_test.exe; \
cp $(ERL_TOP)/bin/$(TARGET)/erlc.exe $(ERL_TOP)/bin/erlc.exe; \
cp $(ERL_TOP)/bin/$(TARGET)/erl.exe $(ERL_TOP)/bin/erl.exe; \
cp $(ERL_TOP)/bin/$(TARGET)/werl.exe $(ERL_TOP)/bin/werl.exe; \
@@ -117,7 +120,8 @@ local_setup:
$(ERL_TOP)/erts/etc/unix/cerl.src > $(ERL_TOP)/bin/cerl; \
cp $(ERL_TOP)/bin/$(TARGET)/dialyzer $(ERL_TOP)/bin/dialyzer; \
cp $(ERL_TOP)/bin/$(TARGET)/typer $(ERL_TOP)/bin/typer; \
- cp $(ERL_TOP)/bin/$(TARGET)/run_test $(ERL_TOP)/bin/run_test; \
+ cp $(ERL_TOP)/bin/$(TARGET)/ct_run $(ERL_TOP)/bin/ct_run; \
+ ln -s $(ERL_TOP)/bin/ct_run $(ERL_TOP)/bin/run_test; \
cp $(ERL_TOP)/bin/$(TARGET)/erlc $(ERL_TOP)/bin/erlc; \
cp $(ERL_TOP)/bin/$(TARGET)/escript $(ERL_TOP)/bin/escript; \
chmod 755 $(ERL_TOP)/bin/erl $(ERL_TOP)/bin/erlc \
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 07b4167b27..7793f60f4f 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -1348,6 +1348,13 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
argv[j++] = argv[i];
}
*argc = j;
+#if HALFWORD_HEAP
+ /* If halfword heap, silently ignore any disabling of internal
+ allocators */
+ for (i = 0; i < aui_sz; ++i)
+ aui[i]->enable = 1;
+#endif
+
}
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 1dd9c8bd4a..a680097c2d 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -99,6 +99,16 @@ static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp)
return hp;
}
+#if SIZEOF_LONG != ERTS_SIZEOF_ETERM
+static ERTS_INLINE void ensure_heap(ErlNifEnv* env, unsigned may_need)
+{
+ if (env->hp + may_need > env->hp_end) {
+ alloc_heap_heavy(env, may_need, env->hp);
+ env->hp -= may_need;
+ }
+}
+#endif
+
void erts_pre_nif(ErlNifEnv* env, Process* p, struct erl_module_nif* mod_nif)
{
env->mod_nif = mod_nif;
@@ -730,9 +740,8 @@ int enif_get_long(ErlNifEnv* env, Eterm term, long* ip)
{
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return term_to_Sint(term, ip);
-#elif SIZEOF_INT == ERTS_SIZEOF_ETERM
- Sint i;
- return term_to_Sint(term, &i) ? (*ip = (long) i, 1) : 0;
+#elif SIZEOF_LONG == 8
+ return term_to_Sint64(term, ip);
#else
# error Unknown long word size
#endif
@@ -742,9 +751,8 @@ int enif_get_ulong(ErlNifEnv* env, Eterm term, unsigned long* ip)
{
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return term_to_Uint(term, ip);
-#elif SIZEOF_INT == ERTS_SIZEOF_ETERM
- Uint u;
- return term_to_Uint(term, &u) ? (*ip = (unsigned long) u, 1) : 0;
+#elif SIZEOF_LONG == 8
+ return term_to_Uint64(term, ip);
#else
# error Unknown long word size
#endif
@@ -821,12 +829,22 @@ ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned i)
ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i)
{
+#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return IS_SSMALL(i) ? make_small(i) : small_to_big(i, alloc_heap(env,2));
+#elif SIZEOF_LONG == 8
+ ensure_heap(env,3);
+ return erts_sint64_to_big(i, &env->hp);
+#endif
}
ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i)
{
+#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2));
+#elif SIZEOF_LONG == 8
+ ensure_heap(env,3);
+ return erts_uint64_to_big(i, &env->hp);
+#endif
}
#if HAVE_INT64 && SIZEOF_LONG != 8
diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c
index 04bd1139f5..6de08e2fa6 100644..100755
--- a/erts/emulator/drivers/win32/win_efile.c
+++ b/erts/emulator/drivers/win32/win_efile.c
@@ -862,6 +862,7 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
findbuf.nFileSizeLow = 0;
findbuf.cFileName[0] = '\0';
+ pInfo->links = 1;
pInfo->modifyTime.year = 1980;
pInfo->modifyTime.month = 1;
pInfo->modifyTime.day = 1;
@@ -874,6 +875,33 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
SYSTEMTIME SystemTime;
FILETIME LocalFTime;
+ /*first check if we are a symlink */
+ if (!info_for_link && (findbuf.dwFileAttributes &
+ FILE_ATTRIBUTE_REPARSE_POINT)){
+ /*
+ * given that we know this is a symlink,
+ we should be able to find its target */
+ char target_name[256];
+ if (efile_readlink(errInfo, name, target_name,256) == 1) {
+ return efile_fileinfo(errInfo, pInfo,
+ target_name, info_for_link);
+ }
+ }
+
+#if 0
+ /* number of links: */
+ {
+ HANDLE handle; /* Handle returned by CreateFile() */
+ BY_HANDLE_FILE_INFORMATION fileInfo; /* from CreateFile() */
+ if (handle = CreateFile(name, GENERIC_READ, 0,NULL,
+ OPEN_EXISTING, 0, NULL)) {
+ GetFileInformationByHandle(handle, &fileInfo);
+ pInfo->links = fileInfo.nNumberOfLinks;
+ CloseHandle(handle);
+ }
+ }
+#endif
+
#define GET_TIME(dst, src) \
if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \
!FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \
@@ -908,7 +936,10 @@ if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \
pInfo->size_low = findbuf.nFileSizeLow;
pInfo->size_high = findbuf.nFileSizeHigh;
- if (findbuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ if (info_for_link && (findbuf.dwFileAttributes &
+ FILE_ATTRIBUTE_REPARSE_POINT))
+ pInfo->type = FT_SYMLINK;
+ else if (findbuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
pInfo->type = FT_DIRECTORY;
else
pInfo->type = FT_REGULAR;
@@ -919,7 +950,6 @@ if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \
pInfo->access = FA_READ|FA_WRITE;
pInfo->mode = dos_to_posix_mode(findbuf.dwFileAttributes, name);
- pInfo->links = 1;
pInfo->major_device = drive;
pInfo->minor_device = 0;
pInfo->inode = 0;
@@ -1082,12 +1112,17 @@ char* buf; /* Buffer to write. */
size_t count; /* Number of bytes to write. */
{
DWORD written; /* Bytes written in last operation. */
+ OVERLAPPED overlapped;
+ OVERLAPPED* pOverlapped = NULL;
if (flags & EFILE_MODE_APPEND) {
- (void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.Offset = 0xffffffff;
+ overlapped.OffsetHigh = 0xffffffff;
+ pOverlapped = &overlapped;
}
while (count > 0) {
- if (!WriteFile((HANDLE) fd, buf, count, &written, NULL))
+ if (!WriteFile((HANDLE) fd, buf, count, &written, pOverlapped))
return set_error(errInfo);
buf += written;
count -= written;
@@ -1107,11 +1142,16 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
size_t size) /* Number of bytes to write */
{
int cnt; /* Buffers so far written */
+ OVERLAPPED overlapped;
+ OVERLAPPED* pOverlapped = NULL;
ASSERT(iovcnt >= 0);
if (flags & EFILE_MODE_APPEND) {
- (void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.Offset = 0xffffffff;
+ overlapped.OffsetHigh = 0xffffffff;
+ pOverlapped = &overlapped;
}
for (cnt = 0; cnt < iovcnt; cnt++) {
if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
@@ -1123,7 +1163,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
iov[cnt].iov_base + p,
iov[cnt].iov_len - p,
&w,
- NULL))
+ pOverlapped))
return set_error(errInfo);
}
}
@@ -1343,6 +1383,48 @@ dos_to_posix_mode(int attr, const char *name)
int
efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
{
+ /*
+ * load dll and see if we have CreateSymbolicLink at runtime:
+ * (Vista only)
+ */
+ HINSTANCE hModule = NULL;
+ if ((hModule = LoadLibrary("kernel32.dll")) != NULL) {
+ typedef DWORD (WINAPI * GETFINALPATHNAMEBYHANDLEPTR)(
+ HANDLE hFile,
+ LPCSTR lpFilePath,
+ DWORD cchFilePath,
+ DWORD dwFlags);
+
+ GETFINALPATHNAMEBYHANDLEPTR pGetFinalPathNameByHandle =
+ (GETFINALPATHNAMEBYHANDLEPTR)GetProcAddress(hModule, "GetFinalPathNameByHandleA");
+
+ if (pGetFinalPathNameByHandle == NULL) {
+ FreeLibrary(hModule);
+ } else {
+ /* first check if file is a symlink; {error, einval} otherwise */
+ DWORD fileAttributes = GetFileAttributes(name);
+ if ((fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+ BOOLEAN success = 0;
+ HANDLE h = CreateFile(name, GENERIC_READ, 0,NULL, OPEN_EXISTING, 0, NULL);
+ if(h != INVALID_HANDLE_VALUE) {
+ success = pGetFinalPathNameByHandle(h, buffer, size,0);
+ /* GetFinalPathNameByHandle prepends path with "\\?\": */
+ sprintf(buffer, buffer+4);
+ CloseHandle(h);
+ }
+ FreeLibrary(hModule);
+ if (success) {
+ return 1;
+ } else {
+ return set_error(errInfo);
+ }
+ } else {
+ FreeLibrary(hModule);
+ errno = EINVAL;
+ return check_error(-1, errInfo);
+ }
+ }
+ }
errno = ENOTSUP;
return check_error(-1, errInfo);
}
@@ -1427,13 +1509,46 @@ efile_altname(Efile_error* errInfo, char* orig_name, char* buffer, size_t size)
int
efile_link(Efile_error* errInfo, char* old, char* new)
{
- errno = ENOTSUP;
- return check_error(-1, errInfo);
+ if(!CreateHardLink(new, old, NULL)) {
+ return set_error(errInfo);
+ }
+ return 1;
}
int
efile_symlink(Efile_error* errInfo, char* old, char* new)
{
+ /*
+ * Load dll and see if we have CreateSymbolicLink at runtime:
+ * (Vista only)
+ */
+ HINSTANCE hModule = NULL;
+ if ((hModule = LoadLibrary("kernel32.dll")) != NULL) {
+ typedef BOOLEAN (WINAPI * CREATESYMBOLICLINKFUNCPTR) (
+ LPCSTR lpSymlinkFileName,
+ LPCSTR lpTargetFileName,
+ DWORD dwFlags);
+
+ CREATESYMBOLICLINKFUNCPTR pCreateSymbolicLink =
+ (CREATESYMBOLICLINKFUNCPTR) GetProcAddress(hModule,
+ "CreateSymbolicLinkA");
+ /* A for MBCS, W for UNICODE... char* above implies 'A'! */
+ if (pCreateSymbolicLink != NULL) {
+ DWORD attr = GetFileAttributes(old);
+ int flag = (attr != INVALID_FILE_ATTRIBUTES &&
+ attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
+ /* SYMBOLIC_LINK_FLAG_DIRECTORY = 1 */
+ BOOLEAN success = pCreateSymbolicLink(new, old, flag);
+ FreeLibrary(hModule);
+
+ if (success) {
+ return 1;
+ } else {
+ return set_error(errInfo);
+ }
+ } else
+ FreeLibrary(hModule);
+ }
errno = ENOTSUP;
return check_error(-1, errInfo);
}
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index d24347b3aa..39b04b26a9 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -97,7 +97,7 @@ static int driver_write(long, HANDLE, byte*, int);
static void common_stop(int);
static int create_file_thread(struct async_io* aio, int mode);
#ifdef ERTS_SMP
-static void close_active_handles(ErlDrvPort, const HANDLE* handles, int cnt);
+static void close_active_handle(ErlDrvPort, HANDLE handle);
static DWORD WINAPI threaded_handle_closer(LPVOID param);
#endif
static DWORD WINAPI threaded_reader(LPVOID param);
@@ -137,7 +137,11 @@ static BOOL win_console = FALSE;
static OSVERSIONINFO int_os_version; /* Version information for Win32. */
-#ifdef ERTS_SMP
+/*#define USE_CANCELIOEX
+ Disabled the use of CancelIoEx as its been seen to cause problem with some
+ drivers. Not sure what to blame; faulty drivers or some form of invalid use.
+*/
+#if defined(ERTS_SMP) && defined(USE_CANCELIOEX)
static BOOL (WINAPI *fpCancelIoEx)(HANDLE,LPOVERLAPPED);
#endif
@@ -684,6 +688,7 @@ release_driver_data(DriverData* dp)
erts_smp_mtx_lock(&sys_driver_data_lock);
#ifdef ERTS_SMP
+#ifdef USE_CANCELIOEX
if (fpCancelIoEx != NULL) {
if (dp->in.thread == (HANDLE) -1 && dp->in.fd != INVALID_HANDLE_VALUE) {
(*fpCancelIoEx)(dp->in.fd, NULL);
@@ -692,10 +697,12 @@ release_driver_data(DriverData* dp)
(*fpCancelIoEx)(dp->out.fd, NULL);
}
}
- else {
+ else
+#endif
+ {
/* This is a workaround for the fact that CancelIo cant cancel
requests issued by another thread and that we cant use
- CancelIoEx as that's only availabele in Vista etc.
+ CancelIoEx as that's only available in Vista etc.
R14: Avoid scheduler deadlock by only wait for 10ms, and then spawn
a thread that will keep waiting in in order to close handles. */
HANDLE handles[2];
@@ -706,7 +713,7 @@ release_driver_data(DriverData* dp)
dp->in.fd = INVALID_HANDLE_VALUE;
DEBUGF(("Waiting for the in event thingie"));
if (WaitForSingleObject(dp->in.ov.hEvent,timeout) == WAIT_TIMEOUT) {
- handles[i++] = dp->in.ov.hEvent;
+ close_active_handle(dp->port_num, dp->in.ov.hEvent);
dp->in.ov.hEvent = NULL;
timeout = 0;
}
@@ -717,14 +724,11 @@ release_driver_data(DriverData* dp)
dp->out.fd = INVALID_HANDLE_VALUE;
DEBUGF(("Waiting for the out event thingie"));
if (WaitForSingleObject(dp->out.ov.hEvent,timeout) == WAIT_TIMEOUT) {
- handles[i++] = dp->out.ov.hEvent;
+ close_active_handle(dp->port_num, dp->out.ov.hEvent);
dp->out.ov.hEvent = NULL;
}
DEBUGF(("...done\n"));
}
- if (i > 0) {
- close_active_handles(dp->port_num, handles, i);
- }
}
#else
if (dp->in.thread == (HANDLE) -1 && dp->in.fd != INVALID_HANDLE_VALUE) {
@@ -772,42 +776,82 @@ release_driver_data(DriverData* dp)
#ifdef ERTS_SMP
-struct handles_to_be_closed
-{
- int cnt;
- HANDLE handles[2];
+struct handles_to_be_closed {
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ unsigned cnt;
};
+static struct handles_to_be_closed* htbc_curr = NULL;
+CRITICAL_SECTION htbc_lock;
-static void close_active_handles(ErlDrvPort port_num, const HANDLE* handles, int cnt)
+static void close_active_handle(ErlDrvPort port_num, HANDLE handle)
{
- DWORD tid;
- HANDLE thread;
+ struct handles_to_be_closed* htbc;
int i;
- struct handles_to_be_closed* htbc = erts_alloc(ERTS_ALC_T_DRV_TAB,
- sizeof(struct handles_to_be_closed));
- htbc->cnt = cnt;
- for (i=0; i < cnt; ++i) {
- htbc->handles[i] = handles[i];
- (void) driver_select(port_num, (ErlDrvEvent)handles[i],
- ERL_DRV_USE_NO_CALLBACK, 0);
+ EnterCriticalSection(&htbc_lock);
+ htbc = htbc_curr;
+ if (htbc == NULL || htbc->cnt >= MAXIMUM_WAIT_OBJECTS) {
+ DWORD tid;
+ HANDLE thread;
+
+ htbc = (struct handles_to_be_closed*) erts_alloc(ERTS_ALC_T_DRV_TAB,
+ sizeof(*htbc));
+ htbc->handles[0] = CreateAutoEvent(FALSE);
+ htbc->cnt = 1;
+ thread = (HANDLE *) _beginthreadex(NULL, 0, threaded_handle_closer, htbc, 0, &tid);
+ CloseHandle(thread);
}
- thread = (HANDLE *) _beginthreadex(NULL, 0, threaded_handle_closer, htbc, 0, &tid);
- CloseHandle(thread);
+ htbc->handles[htbc->cnt++] = handle;
+ driver_select(port_num, (ErlDrvEvent)handle, ERL_DRV_USE_NO_CALLBACK, 0);
+ SetEvent(htbc->handles[0]);
+ htbc_curr = htbc;
+ LeaveCriticalSection(&htbc_lock);
}
-
static DWORD WINAPI
threaded_handle_closer(LPVOID param)
{
struct handles_to_be_closed* htbc = (struct handles_to_be_closed*) param;
- int i;
- DEBUGF(("threaded_handle_closer waiting for %d handles\r\n",htbc->cnt));
- WaitForMultipleObjects(htbc->cnt, htbc->handles, TRUE, INFINITE);
- for (i=0; i < htbc->cnt; ++i) {
- CloseHandle(htbc->handles[i]);
+ unsigned ix;
+ DWORD res;
+ DEBUGF(("threaded_handle_closer %p started\r\n", htbc));
+ EnterCriticalSection(&htbc_lock);
+ for (;;) {
+ {
+ HANDLE* handles = htbc->handles;
+ unsigned cnt = htbc->cnt;
+ DWORD timeout = (htbc == htbc_curr) ? INFINITE : 10*1000;
+
+ LeaveCriticalSection(&htbc_lock);
+ DEBUGF(("threaded_handle_closer %p waiting for %d handles\r\n", htbc, cnt));
+ res = WaitForMultipleObjects(cnt, handles, FALSE, timeout);
+ }
+ EnterCriticalSection(&htbc_lock);
+ switch (res) {
+ case WAIT_OBJECT_0:
+ case WAIT_TIMEOUT:
+ break; /* got some more handles to wait for maybe */
+ default:
+ ix = res - WAIT_OBJECT_0;
+ if (ix > 0 && ix < htbc->cnt) {
+ CloseHandle(htbc->handles[ix]);
+ htbc->handles[ix] = htbc->handles[--htbc->cnt];
+ }
+ }
+ if (htbc != htbc_curr) {
+ if (htbc->cnt == 1) { /* no real handles left */
+ break;
+ }
+ /* The thread with most free slots will be "current" */
+ if (htbc->cnt < htbc_curr->cnt) {
+ htbc_curr = htbc;
+ DEBUGF(("threaded_handle_closer %p made current\r\n", htbc));
+ }
+ }
}
+ LeaveCriticalSection(&htbc_lock);
+ CloseHandle(htbc->handles[0]);
erts_free(ERTS_ALC_T_DRV_TAB, htbc);
- DEBUGF(("threaded_handle_closer terminating\r\n"));
+ DEBUGF(("threaded_handle_closer %p terminating\r\n", htbc));
return 0;
}
#endif /* ERTS_SMP */
@@ -1101,11 +1145,10 @@ static int
spawn_init()
{
int i;
-#ifdef ERTS_SMP
+#if defined(ERTS_SMP) && defined(USE_CANCELIOEX)
HMODULE module = GetModuleHandle("kernel32");
- fpCancelIoEx = (module != NULL) ?
- (BOOL (WINAPI *)(HANDLE,LPOVERLAPPED))
- GetProcAddress(module,"CancelIoEx") : NULL;
+ fpCancelIoEx = (BOOL (WINAPI *)(HANDLE,LPOVERLAPPED))
+ ((module != NULL) ? GetProcAddress(module,"CancelIoEx") : NULL);
DEBUGF(("fpCancelIoEx = %p\r\n", fpCancelIoEx));
#endif
driver_data = (struct driver_data *)
@@ -3068,6 +3111,7 @@ void erl_sys_init(void)
#ifdef ERTS_SMP
erts_smp_tsd_key_create(&win32_errstr_key);
+ InitializeCriticalSection(&htbc_lock);
#endif
erts_smp_atomic_init(&pipe_creation_counter,0);
/*
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index a7476ca9bb..6d89653623 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -2308,8 +2308,28 @@ close_deaf_port(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:seconds(100)),
?line DataDir = ?config(data_dir, Config),
?line DeadPort = os:find_executable("dead_port", DataDir),
-
?line Port = open_port({spawn,DeadPort++" 60"},[]),
?line erlang:port_command(Port,"Hello, can you hear me!?!?"),
?line port_close(Port),
- ok.
+
+ close_deaf_port_1(0, DeadPort).
+
+close_deaf_port_1(1000, _) ->
+ ok;
+close_deaf_port_1(N, Cmd) ->
+ Timeout = integer_to_list(random:uniform(10*1000)),
+ try open_port({spawn,Cmd++" "++Timeout},[]) of
+ Port ->
+ ?line erlang:port_command(Port,"Hello, can you hear me!?!?"),
+ ?line port_close(Port),
+ close_deaf_port_1(N+1, Cmd)
+ catch
+ exit:eagain ->
+ {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."}
+ end.
+
+
+repeat(0, _) -> ok;
+repeat(Cnt, Fun) ->
+ Fun(),
+ repeat(Cnt-1, Fun).
diff --git a/erts/emulator/test/port_SUITE_data/dead_port.c b/erts/emulator/test/port_SUITE_data/dead_port.c
index 6fa77112be..68e96fbf14 100644
--- a/erts/emulator/test/port_SUITE_data/dead_port.c
+++ b/erts/emulator/test/port_SUITE_data/dead_port.c
@@ -72,14 +72,14 @@ char *argv[];
{
int x;
if (argc < 2) {
- fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ fprintf(stderr,"Usage %s <milliseconds>\n",argv[0]);
return 1;
}
if ((x = atoi(argv[1])) <= 0) {
- fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ fprintf(stderr,"Usage %s <milliseconds>\n",argv[0]);
return 1;
}
- delay(x*1000);
+ delay(x);
return 0;
}
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index e866511153..4754328c0b 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -178,7 +178,7 @@ MC_OUTPUTS= \
MT_FLAG="-MD"
endif
INET_GETHOST = $(BINDIR)/inet_gethost.exe
-INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe $(BINDIR)/run_test.exe
+INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe $(BINDIR)/ct_run.exe
INSTALL_SRC = $(WINETC)/start_erl.c $(WINETC)/Nmakefile.start_erl
ERLEXECDIR=.
INSTALL_LIBS =
@@ -211,7 +211,7 @@ ERLSRV_OBJECTS=
MC_OUTPUTS=
INET_GETHOST = $(BINDIR)/inet_gethost@EXEEXT@
INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer@EXEEXT@ $(BINDIR)/dialyzer@EXEEXT@ \
- $(BINDIR)/erlc@EXEEXT@ $(BINDIR)/escript@EXEEXT@ $(BINDIR)/run_test@EXEEXT@ \
+ $(BINDIR)/erlc@EXEEXT@ $(BINDIR)/escript@EXEEXT@ $(BINDIR)/ct_run@EXEEXT@ \
$(BINDIR)/run_erl $(BINDIR)/to_erl $(BINDIR)/dyn_erl
INSTALL_EMBEDDED_DATA = ../unix/start.src ../unix/start_erl.src
INSTALL_TOP = Install
@@ -274,7 +274,7 @@ endif
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/dyn_erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/safe_string.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/typer.o
- rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_test.o
+ rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/ct_run.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/vxcall.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/werl.o
@@ -350,11 +350,11 @@ $(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o
$(OBJDIR)/escript.o: escript.c
$(CC) $(CFLAGS) -o $@ -c escript.c
-$(BINDIR)/run_test@EXEEXT@: $(OBJDIR)/run_test.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/run_test.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-$(OBJDIR)/run_test.o: run_test.c
- $(CC) $(CFLAGS) -o $@ -c run_test.c
+$(OBJDIR)/ct_run.o: ct_run.c
+ $(CC) $(CFLAGS) -o $@ -c ct_run.c
#------------------------------------------------------------------------
diff --git a/erts/etc/common/run_test.c b/erts/etc/common/ct_run.c
index 042b8571ca..7aaab716f7 100644
--- a/erts/etc/common/run_test.c
+++ b/erts/etc/common/ct_run.c
@@ -85,6 +85,7 @@ static char* strsave(char* string);
static void push_words(char* src);
static int run_erlang(char* name, char** argv);
static char* get_default_emulator(char* progname);
+static void print_deprecation_warning(char *progname);
#ifdef __WIN32__
static char* possibly_quote(char* arg);
#endif
@@ -131,6 +132,8 @@ main(int argc, char** argv)
int erl_args;
char** argv0 = argv;
+ print_deprecation_warning(argv[0]);
+
emulator = get_default_emulator(argv[0]);
/*
@@ -391,7 +394,7 @@ run_erlang(char* progname, char** argv)
status = my_spawnvp(argv)/*_spawnvp(_P_WAIT,progname,argv)*/;
if (status == -1) {
- fprintf(stderr, "run_test: Error executing '%s': %d", progname,
+ fprintf(stderr, "ct_run: Error executing '%s': %d", progname,
GetLastError());
}
return status;
@@ -411,7 +414,7 @@ error(char* format, ...)
va_start(ap, format);
erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
- fprintf(stderr, "run_test: %s\n", sbuf);
+ fprintf(stderr, "ct_run: %s\n", sbuf);
exit(1);
}
@@ -432,6 +435,27 @@ strsave(char* string)
return p;
}
+/* Instead of making sure basename exists, we do our own */
+static char *simple_basename(char *path)
+{
+ char *ptr;
+ for (ptr = path; *ptr != '\0'; ++ptr) {
+ if (*ptr == '/' || *ptr == '\\') {
+ path = ptr + 1;
+ }
+ }
+ return path;
+}
+
+static void print_deprecation_warning(char* progpath)
+{
+ char *basename = simple_basename(progpath);
+ if(strcmp(basename,"run_test") == 0 ||
+ strcmp(basename, "run_test.exe") == 0) {
+ printf("---***---\nDeprecated: run_test is deprecated and will be removed in R16B,\n please use ct_run instead\n---***---\n");
+ }
+}
+
static char*
get_default_emulator(char* progname)
{
diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src
index 7dead62ab0..8f40c43874 100644
--- a/erts/etc/unix/Install.src
+++ b/erts/etc/unix/Install.src
@@ -89,9 +89,12 @@ cp -p $ERL_ROOT/erts-%I_VSN%/bin/erl .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/erlc .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/dialyzer .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/typer .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/run_test .
+cp -p $ERL_ROOT/erts-%I_VSN%/bin/ct_run .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/escript .
+# Remove in R16B
+ln -s ct_run run_test
+
#
# Set a soft link to epmd
# This should not be done for an embedded system!
diff --git a/erts/etc/win32/Install.c b/erts/etc/win32/Install.c
index ca814e3f80..6e60512f6d 100644
--- a/erts/etc/win32/Install.c
+++ b/erts/etc/win32/Install.c
@@ -46,7 +46,7 @@ int main(int argc, char **argv)
HANDLE module = GetModuleHandle(NULL);
char *binaries[] = { "erl.exe", "werl.exe", "erlc.exe",
"dialyzer.exe", "typer.exe",
- "escript.exe", "run_test.exe", NULL };
+ "escript.exe", "ct_run.exe", NULL };
char *scripts[] = { "start_clean.boot", "start_sasl.boot", NULL };
char fromname[MAX_PATH];
char toname[MAX_PATH];
@@ -172,6 +172,20 @@ int main(int argc, char **argv)
}
}
+ // Remove in R16B
+ sprintf(fromname,"%s\\%s",bin_dir,"ct_run.exe");
+ sprintf(toname,"%s\\%s",bin_dir,"run_test.exe");
+ if (GetFileAttributes(fromname) == 0xFFFFFFFF) {
+ fprintf(stderr,"Could not find file %s\n",
+ fromname);
+ exit(1);
+ }
+ if (!CopyFile(fromname,toname,FALSE)) {
+ fprintf(stderr,"Could not copy file %s to %s\n",
+ fromname,toname);
+ fprintf(stderr,"Continuing installation anyway...\n");
+ }
+
for (i = 0; scripts[i] != NULL; ++i) {
sprintf(fromname,"%s\\%s",release_dir,scripts[i]);
sprintf(toname,"%s\\%s",bin_dir,scripts[i]);
diff --git a/erts/etc/win32/cygwin_tools/vc/ld.sh b/erts/etc/win32/cygwin_tools/vc/ld.sh
index 9a38c10748..406c63ffee 100755
--- a/erts/etc/win32/cygwin_tools/vc/ld.sh
+++ b/erts/etc/win32/cygwin_tools/vc/ld.sh
@@ -158,7 +158,7 @@ else
fi
p=$$
-CMD="$linktype -nologo -incremental:no $CMD $STDLIB $DEFAULT_LIBRARIES"
+CMD="$linktype -nologo -incremental:no -largeaddressaware $CMD $STDLIB $DEFAULT_LIBRARIES"
if [ "X$LD_SH_DEBUG_LOG" != "X" ]; then
echo ld.sh "$SAVE" >>$LD_SH_DEBUG_LOG
echo link.exe $CMD >>$LD_SH_DEBUG_LOG