aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_async.c1
-rw-r--r--erts/emulator/test/driver_SUITE.erl38
-rw-r--r--erts/emulator/test/driver_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_9302_drv.c232
-rw-r--r--erts/epmd/test/epmd_SUITE.erl139
5 files changed, 344 insertions, 69 deletions
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 12c7631448..a920bd2c8c 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -251,6 +251,7 @@ static int async_del(long id)
erts_free(ERTS_ALC_T_ASYNC, a);
return 1;
}
+ a = a->next;
}
erts_mtx_unlock(&async_q[i].mtx);
}
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index 520e3e8c76..f6cf01ce16 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -74,7 +74,8 @@
missing_callbacks/1,
smp_select/1,
driver_select_use/1,
- thread_mseg_alloc_cache_clean/1]).
+ thread_mseg_alloc_cache_clean/1,
+ otp_9302/1]).
-export([bin_prefix/2]).
@@ -141,7 +142,8 @@ all() ->
smaller_minor_vsn_drv, peek_non_existing_queue,
otp_6879, caller, many_events, missing_callbacks,
smp_select, driver_select_use,
- thread_mseg_alloc_cache_clean].
+ thread_mseg_alloc_cache_clean,
+ otp_9302].
groups() ->
[{timer, [],
@@ -1890,13 +1892,39 @@ thread_mseg_alloc_cache_clean_test(Port, N, CCI, Size) ->
?line ?t:format("CCC = ~p~n", [CCC]),
?line true = CCC > OCCC,
?line thread_mseg_alloc_cache_clean_test(Port, N-1, CCI, Size).
-
-
+
+otp_9302(Config) when is_list(Config) ->
+ ?line Path = ?config(data_dir, Config),
+ ?line erl_ddll:start(),
+ ?line ok = load_driver(Path, otp_9302_drv),
+ ?line Port = open_port({spawn, otp_9302_drv}, []),
+ ?line true = is_port(Port),
+ ?line port_command(Port, ""),
+ ?line {msg, block} = get_port_msg(Port, infinity),
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line case erlang:system_info(thread_pool_size) of
+ 0 ->
+ {msg, cancel} = get_port_msg(Port, infinity);
+ _ ->
+ ok
+ end,
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line {msg, end_of_jobs} = get_port_msg(Port, infinity),
+ ?line no_msg = get_port_msg(Port, 2000),
+ ?line port_close(Port),
+ ?line ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Utilities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+
+get_port_msg(Port, Timeout) ->
+ receive
+ {Port, What} ->
+ {msg, What}
+ after Timeout ->
+ no_msg
+ end.
wait_until(Fun) ->
case Fun() of
diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src
index 4ac7987d2f..5b3ba1557e 100644
--- a/erts/emulator/test/driver_SUITE_data/Makefile.src
+++ b/erts/emulator/test/driver_SUITE_data/Makefile.src
@@ -11,7 +11,8 @@ MISC_DRVS = outputv_drv@dll@ \
caller_drv@dll@ \
many_events_drv@dll@ \
missing_callback_drv@dll@ \
- thr_alloc_drv@dll@
+ thr_alloc_drv@dll@ \
+ otp_9302_drv@dll@
SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \
sys_info_1_1_drv@dll@ \
diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
new file mode 100644
index 0000000000..beee1b735f
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
@@ -0,0 +1,232 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. 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%
+ */
+#ifdef __WIN32__
+#include <windows.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "erl_driver.h"
+
+static void stop(ErlDrvData drv_data);
+static ErlDrvData start(ErlDrvPort port,
+ char *command);
+static void output(ErlDrvData drv_data,
+ char *buf, int len);
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data);
+
+static ErlDrvEntry otp_9302_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ output,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ "otp_9302_drv",
+ NULL /* finish */,
+ NULL /* handle */,
+ NULL /* control */,
+ NULL /* timeout */,
+ NULL /* outputv */,
+ ready_async,
+ NULL /* flush */,
+ NULL /* call */,
+ NULL /* event */,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERL_DRV_FLAG_USE_PORT_LOCKING,
+ NULL /* handle2 */,
+ NULL /* handle_monitor */
+};
+
+typedef struct Otp9302AsyncData_ Otp9302AsyncData;
+
+typedef struct {
+ ErlDrvMutex *mtx;
+ Otp9302AsyncData *start;
+ Otp9302AsyncData *end;
+} Otp9302MsgQ;
+
+typedef struct {
+ ErlDrvPort port;
+ int smp;
+ Otp9302MsgQ msgq;
+} Otp9302Data;
+
+struct Otp9302AsyncData_ {
+ Otp9302AsyncData *next;
+ ErlDrvPort port;
+ int smp;
+ int refc;
+ int block;
+ struct {
+ ErlDrvTermData port;
+ ErlDrvTermData receiver;
+ ErlDrvTermData msg;
+ } term_data;
+ Otp9302MsgQ *msgq;
+};
+
+
+DRIVER_INIT(otp_9302_drv)
+{
+ return &otp_9302_drv_entry;
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ Otp9302Data *data = (Otp9302Data *) drv_data;
+ if (!data->smp)
+ erl_drv_mutex_destroy(data->msgq.mtx);
+ driver_free(data);
+}
+
+static ErlDrvData start(ErlDrvPort port,
+ char *command)
+{
+ Otp9302Data *data;
+ ErlDrvSysInfo sys_info;
+
+ data = driver_alloc(sizeof(Otp9302Data));
+ if (!data)
+ return ERL_DRV_ERROR_GENERAL;
+
+ data->port = port;
+
+ driver_system_info(&sys_info, sizeof(ErlDrvSysInfo));
+ data->smp = sys_info.smp_support;
+
+ if (!data->smp) {
+ data->msgq.start = NULL;
+ data->msgq.end = NULL;
+ data->msgq.mtx = erl_drv_mutex_create("");
+ if (!data->msgq.mtx) {
+ driver_free(data);
+ return ERL_DRV_ERROR_GENERAL;
+ }
+ }
+
+ return (ErlDrvData) data;
+}
+
+static void send_reply(Otp9302AsyncData *adata)
+{
+ ErlDrvTermData spec[] = {
+ ERL_DRV_PORT, adata->term_data.port,
+ ERL_DRV_ATOM, adata->term_data.msg,
+ ERL_DRV_TUPLE, 2
+ };
+ driver_send_term(adata->port, adata->term_data.receiver,
+ spec, sizeof(spec)/sizeof(spec[0]));
+}
+
+static void enqueue_reply(Otp9302AsyncData *adata)
+{
+ Otp9302MsgQ *msgq = adata->msgq;
+ adata->next = NULL;
+ adata->refc++;
+ erl_drv_mutex_lock(msgq->mtx);
+ if (msgq->end)
+ msgq->end->next = adata;
+ else
+ msgq->end = msgq->start = adata;
+ msgq->end = adata;
+ erl_drv_mutex_unlock(msgq->mtx);
+}
+
+static void dequeue_replies(Otp9302AsyncData *adata)
+{
+ Otp9302MsgQ *msgq = adata->msgq;
+ erl_drv_mutex_lock(msgq->mtx);
+ if (--adata->refc == 0)
+ driver_free(adata);
+ while (msgq->start) {
+ send_reply(msgq->start);
+ adata = msgq->start;
+ msgq->start = msgq->start->next;
+ if (--adata->refc == 0)
+ driver_free(adata);
+ }
+ msgq->start = msgq->end = NULL;
+ erl_drv_mutex_unlock(msgq->mtx);
+}
+
+static void async_invoke(void *data)
+{
+ Otp9302AsyncData *adata = (Otp9302AsyncData *) data;
+ if (adata->block) {
+#ifdef __WIN32__
+ Sleep((DWORD) 2000);
+#else
+ sleep(2);
+#endif
+ }
+ if (adata->smp)
+ send_reply(adata);
+ else
+ enqueue_reply(adata);
+}
+
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data)
+{
+ Otp9302AsyncData *adata = (Otp9302AsyncData *) thread_data;
+ if (adata->smp)
+ driver_free(adata);
+ else
+ dequeue_replies(adata);
+}
+
+static void output(ErlDrvData drv_data,
+ char *buf, int len)
+{
+ Otp9302Data *data = (Otp9302Data *) drv_data;
+ ErlDrvTermData td_port = driver_mk_port(data->port);
+ ErlDrvTermData td_receiver = driver_caller(data->port);
+ ErlDrvTermData td_job = driver_mk_atom("job");
+ unsigned int key = (unsigned int) data->port;
+ long id[5];
+ Otp9302AsyncData *ad[5];
+ int i;
+
+ for (i = 0; i < sizeof(ad)/sizeof(ad[0]); i++) {
+ ad[i] = driver_alloc(sizeof(Otp9302AsyncData));
+ if (!ad[i])
+ abort();
+
+ ad[i]->smp = data->smp;
+ ad[i]->port = data->port;
+ ad[i]->block = 0;
+ ad[i]->refc = 1;
+ ad[i]->term_data.port = td_port;
+ ad[i]->term_data.receiver = td_receiver;
+ ad[i]->term_data.msg = td_job;
+ ad[i]->msgq = &data->msgq;
+ }
+ ad[0]->block = 1;
+ ad[0]->term_data.msg = driver_mk_atom("block");
+ ad[2]->term_data.msg = driver_mk_atom("cancel");
+ ad[4]->term_data.msg = driver_mk_atom("end_of_jobs");
+ for (i = 0; i < sizeof(id)/sizeof(id[0]); i++)
+ id[i] = driver_async(data->port, &key, async_invoke, ad[i], driver_free);
+ if (id[2] > 0)
+ driver_async_cancel(id[2]);
+}
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index 72c890503d..6889ec0b34 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -780,42 +780,43 @@ no_nonlocal_register(suite) ->
no_nonlocal_register(doc) ->
["Ensure that we cannot register throug a nonlocal connection"];
no_nonlocal_register(Config) when is_list(Config) ->
+ ?line case {os:find_executable("ssh"),ct:get_config(ssh_proxy_host)} of
+ {SSH,Name} when is_list(Name), is_list(SSH) ->
+ do_no_nonlocal_register(Config,Name);
+ {false,_} ->
+ {skip, "No ssh command found to create proxy"};
+ _ ->
+ {skip, "No ssh_proxy_host configured in ts.config"}
+ end.
+do_no_nonlocal_register(Config,SSHHost) when is_list(Config) ->
?line ok = epmdrun(),
- ?line {ok,Ifs} = inet:getiflist(),
- ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ],
- ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0],
- ?line Addr = lists:filter(fun({127,_,_,_}) ->
- false;
- (_) ->
- true
- end,Addr1),
- %% Now we should have all non loopback interface addresses,
- %% none should accept a alive2 registration.
- ?line Res = lists:map(fun(Ad={A1,A2,A3,A4}) ->
- try
- Name = "gurka_"++
- integer_to_list(A1)++"_"++
- integer_to_list(A2)++"_"++
- integer_to_list(A3)++"_"++
- integer_to_list(A4),
- Bname = list_to_binary(Name),
- NameS = byte_size(Bname),
- ?line Bin= <<$x:8,4747:16,$M:8,0:8,5:16,
- 5:16,NameS:16,Bname/binary,
- 0:16>>,
- ?line S = size(Bin),
- {ok, E} = connect(Ad),
- gen_tcp:send(E,[<<S:16>>,Bin]),
- closed = recv(E,1),
- gen_tcp:close(E),
- true
- catch
- _:_ ->
- false
- end
- end, Addr),
- erlang:display(Res),
- ?line true = alltrue(Res),
+ ?line ProxyPort = proxy_port(),
+ ?line ok = ssh_proxy(SSHHost,ProxyPort),
+ Res = try
+ ?line Name = "gurka_"
+ %++
+ %integer_to_list(A1)++"_"++
+ %integer_to_list(A2)++"_"++
+ %integer_to_list(A3)++"_"++
+ %integer_to_list(A4)
+ ,
+ ?line Bname = list_to_binary(Name),
+ ?line NameS = byte_size(Bname),
+ ?line Bin= <<$x:8,4747:16,$M:8,0:8,5:16,
+ 5:16,NameS:16,Bname/binary,
+ 0:16>>,
+ ?line S = size(Bin),
+ ?line {ok, E} = connect("localhost",ProxyPort,passive),
+ ?line gen_tcp:send(E,[<<S:16>>,Bin]),
+ ?line closed = recv(E,1),
+ ?line gen_tcp:close(E),
+ true
+ catch
+ _:_ ->
+ false
+ end,
+ %erlang:display(Res),
+ true = Res,
ok.
no_nonlocal_kill(suite) ->
@@ -823,35 +824,34 @@ no_nonlocal_kill(suite) ->
no_nonlocal_kill(doc) ->
["Ensure that we cannot kill through nonlocal connection"];
no_nonlocal_kill(Config) when is_list(Config) ->
+ ?line case {os:find_executable("ssh"),ct:get_config(ssh_proxy_host)} of
+ {SSH,Name} when is_list(Name), is_list(SSH) ->
+ do_no_nonlocal_kill(Config,Name);
+ {false,_} ->
+ {skip, "No ssh command found to create proxy"};
+ _ ->
+ {skip, "No ssh_proxy_host configured in ts.config"}
+ end.
+do_no_nonlocal_kill(Config,SSHHost) when is_list(Config) ->
?line ok = epmdrun(),
- ?line {ok,Ifs} = inet:getiflist(),
- ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ],
- ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0],
- ?line Addr = lists:filter(fun({127,_,_,_}) ->
- false;
- (_) ->
- true
- end,Addr1),
- %% Now we should have all non loopback interface addresses,
- %% none should accept a alive2 registration.
- ?line Res = lists:map(fun(Ad) ->
- try
- {ok, E} = connect(Ad),
- M = [?EPMD_KILL_REQ],
- send(E, [size16(M), M]),
- closed = recv(E,2),
- gen_tcp:close(E),
- sleep(?MEDIUM_PAUSE),
- {ok, E2} = connect(Ad),
- gen_tcp:close(E2),
- true
- catch
- _:_ ->
- false
- end
- end, Addr),
- erlang:display(Res),
- ?line true = alltrue(Res),
+ ?line ProxyPort = proxy_port(),
+ ?line ok = ssh_proxy(SSHHost,ProxyPort),
+ Res = try
+ {ok, E} = connect("localhost",ProxyPort,passive),
+ M = [?EPMD_KILL_REQ],
+ send(E, [size16(M), M]),
+ closed = recv(E,2),
+ gen_tcp:close(E),
+ sleep(?MEDIUM_PAUSE),
+ {ok, E2} = connect("localhost",ProxyPort,passive),
+ gen_tcp:close(E2),
+ true
+ catch
+ _:_ ->
+ false
+ end,
+ %erlang:display(Res),
+ true = Res,
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
no_live_killing(doc) ->
@@ -896,6 +896,19 @@ cleanup() ->
true
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Start an ssh channel to simulate remote access
+
+proxy_port() ->
+ ?PORT+1.
+
+ssh_proxy(SSHHost,ProxyPort) ->
+ ?line Host = lists:nth(2,string:tokens(atom_to_list(node()),"@")),
+ % Requires proxy to be a unix host with the command 'read' accessible
+ ?line osrun("ssh -L "++integer_to_list(ProxyPort)++":"++Host++":"
+ ++integer_to_list(?PORT)++" "++SSHHost++" read").
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Normal debug start of epmd