aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Cornish <[email protected]>2015-04-16 15:45:20 -0700
committerZandra Hird <[email protected]>2015-04-23 16:41:14 +0200
commitc08c4a88a73453bd60fb93d0462482a6afc50544 (patch)
treee99e940116eeb7388609a9ac6bd6d482d5f6ee9d
parent1756ef6ea4af36e061cdde92d1a87b3b225edea7 (diff)
downloadotp-c08c4a88a73453bd60fb93d0462482a6afc50544.tar.gz
otp-c08c4a88a73453bd60fb93d0462482a6afc50544.tar.bz2
otp-c08c4a88a73453bd60fb93d0462482a6afc50544.zip
Fix ssh_sftp wait_for_version_negotiation timeout
This patch fixes a bug that causes an SFTP connection to always fail when {timeout, Timeout} option is used with ssh_sftp:start_channel. The bug is that the version negotiation timer is not cancelled upon reception of SSH_FXP_VERSION.
-rw-r--r--lib/ssh/src/ssh_sftp.erl13
1 files changed, 9 insertions, 4 deletions
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index c264eabc78..bab688f226 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -508,12 +508,12 @@ init([Cm, ChannelId, Options]) ->
%%--------------------------------------------------------------------
handle_call({{timeout, infinity}, wait_for_version_negotiation}, From,
#state{xf = #ssh_xfer{vsn = undefined} = Xf} = State) ->
- {noreply, State#state{xf = Xf#ssh_xfer{vsn = From}}};
+ {noreply, State#state{xf = Xf#ssh_xfer{vsn = {wait, From, undefined}}}};
handle_call({{timeout, Timeout}, wait_for_version_negotiation}, From,
#state{xf = #ssh_xfer{vsn = undefined} = Xf} = State) ->
- timer:send_after(Timeout, {timeout, undefined, From}),
- {noreply, State#state{xf = Xf#ssh_xfer{vsn = From}}};
+ TRef = erlang:send_after(Timeout, self(), {timeout, undefined, From}),
+ {noreply, State#state{xf = Xf#ssh_xfer{vsn = {wait, From, TRef}}}};
handle_call({_, wait_for_version_negotiation}, _, State) ->
{reply, ok, State};
@@ -865,7 +865,12 @@ do_handle_reply(#state{xf = Xf} = State,
case Xf#ssh_xfer.vsn of
undefined ->
ok;
- From ->
+ {wait, From, TRef} ->
+ if is_reference(TRef) ->
+ erlang:cancel_timer(TRef);
+ true ->
+ ok
+ end,
ssh_channel:reply(From, ok)
end,
State#state{xf = Xf#ssh_xfer{vsn = Version, ext = Ext}, rep_buf = Rest};