aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/src
diff options
context:
space:
mode:
authorHenrik Nord <[email protected]>2015-10-14 12:42:02 +0200
committerHenrik Nord <[email protected]>2015-10-14 12:42:02 +0200
commit930a0cb98e8a3cc08c70d93472b35d9fdb1dd2f9 (patch)
tree0917e3e56e3e24a5a45bd1afb61c6ea69ec0be2d /lib/ssh/src
parent3c787f47ffc660d77eba3528b10eba570529fb9e (diff)
parent3c799a7ee5ee26f643c7ffad79c81d6156f3dac6 (diff)
downloadotp-930a0cb98e8a3cc08c70d93472b35d9fdb1dd2f9.tar.gz
otp-930a0cb98e8a3cc08c70d93472b35d9fdb1dd2f9.tar.bz2
otp-930a0cb98e8a3cc08c70d93472b35d9fdb1dd2f9.zip
Merge branch 'maint-18' into maint
Conflicts: lib/ssh/vsn.mk
Diffstat (limited to 'lib/ssh/src')
-rw-r--r--lib/ssh/src/ssh.erl4
-rw-r--r--lib/ssh/src/ssh_connection.erl27
2 files changed, 25 insertions, 6 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 15591fb4a7..b6ee29efbb 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -385,6 +385,8 @@ handle_option([{rekey_limit, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{max_sessions, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{max_channels, _} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{negotiation_timeout, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) ->
@@ -443,6 +445,8 @@ handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value
Opt;
handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 ->
Opt;
+handle_ssh_option({max_channels, Value} = Opt) when is_integer(Value), Value>0 ->
+ Opt;
handle_ssh_option({negotiation_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
Opt;
handle_ssh_option({parallel_login, Value} = Opt) when Value==true ; Value==false ->
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 64d2113125..266c64fd4f 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -935,14 +935,27 @@ encode_ip(Addr) when is_list(Addr) ->
end
end.
-start_channel(Cb, Id, Args, SubSysSup) ->
- start_channel(Cb, Id, Args, SubSysSup, undefined).
+start_channel(Cb, Id, Args, SubSysSup, Opts) ->
+ start_channel(Cb, Id, Args, SubSysSup, undefined, Opts).
-start_channel(Cb, Id, Args, SubSysSup, Exec) ->
+start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) ->
ChildSpec = child_spec(Cb, Id, Args, Exec),
ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup),
+ assert_limit_num_channels_not_exceeded(ChannelSup, Opts),
ssh_channel_sup:start_child(ChannelSup, ChildSpec).
+assert_limit_num_channels_not_exceeded(ChannelSup, Opts) ->
+ MaxNumChannels = proplists:get_value(max_channels, Opts, infinity),
+ NumChannels = length([x || {_,_,worker,[ssh_channel]} <-
+ supervisor:which_children(ChannelSup)]),
+ if
+ %% Note that NumChannels is BEFORE starting a new one
+ NumChannels < MaxNumChannels ->
+ ok;
+ true ->
+ throw(max_num_channels_exceeded)
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -998,9 +1011,11 @@ child_spec(Callback, Id, Args, Exec) ->
start_cli(#connection{cli_spec = no_cli}, _) ->
{error, cli_disabled};
-start_cli(#connection{cli_spec = {CbModule, Args}, exec = Exec,
+start_cli(#connection{options = Options,
+ cli_spec = {CbModule, Args},
+ exec = Exec,
sub_system_supervisor = SubSysSup}, ChannelId) ->
- start_channel(CbModule, ChannelId, Args, SubSysSup, Exec).
+ start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options).
start_subsytem(BinName, #connection{options = Options,
sub_system_supervisor = SubSysSup},
@@ -1008,7 +1023,7 @@ start_subsytem(BinName, #connection{options = Options,
Name = binary_to_list(BinName),
case check_subsystem(Name, Options) of
{Callback, Opts} when is_atom(Callback), Callback =/= none ->
- start_channel(Callback, ChannelId, Opts, SubSysSup);
+ start_channel(Callback, ChannelId, Opts, SubSysSup, Options);
{Other, _} when Other =/= none ->
{error, legacy_option_not_supported}
end.