summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolger Weiss <holger@zedat.fu-berlin.de>2014-09-06 20:34:32 +0200
committerHolger Weiss <holger@zedat.fu-berlin.de>2014-09-06 20:34:32 +0200
commit2e169167d4fdb7c69fb57ea8dc9923f7d713760d (patch)
tree39abd0d2cb4dfbda4e48c4309206104f65473d45
parentXEP-0198: Let fsm_next_state/2 check timeout value (diff)
XEP-0198: Change state on gen_tcp:send/2 failure
When Stream Management is enabled and a gen_tcp:send/2 call fails, go into the 'wait_for_resume' state immediately. This makes sure that gen_tcp:send/2 won't be called again, which might avoid an Erlang issue where gen_tcp:send/2 apparently hangs despite 'send_timeout' (and 'send_timeout_close') being set.
-rw-r--r--src/ejabberd_c2s.erl18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 822edc0c..c734d91e 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -1838,7 +1838,8 @@ send_text(StateData, Text) when StateData#state.mgmt_state == active ->
?DEBUG("Send XML on stream = ~p", [Text]),
case catch (StateData#state.sockmod):send(StateData#state.socket, Text) of
{'EXIT', _} ->
- (StateData#state.sockmod):close(StateData#state.socket);
+ (StateData#state.sockmod):close(StateData#state.socket),
+ error;
_ ->
ok
end;
@@ -1857,8 +1858,13 @@ send_element(StateData, El) ->
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == pending ->
mgmt_queue_add(StateData, Stanza);
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == active ->
- send_stanza_and_ack_req(StateData, Stanza),
- mgmt_queue_add(StateData, Stanza);
+ NewStateData = case send_stanza_and_ack_req(StateData, Stanza) of
+ ok ->
+ StateData;
+ error ->
+ StateData#state{mgmt_state = pending}
+ end,
+ mgmt_queue_add(NewStateData, Stanza);
send_stanza(StateData, Stanza) ->
send_element(StateData, Stanza),
StateData.
@@ -2455,13 +2461,15 @@ fsm_next_state_gc(StateName, PackedStateData) ->
%% fsm_next_state: Generate the next_state FSM tuple with different
%% timeout, depending on the future state
+fsm_next_state(session_established, #state{mgmt_state = pending} = StateData) ->
+ fsm_next_state(wait_for_resume, StateData);
fsm_next_state(session_established, StateData) ->
{next_state, session_established, StateData,
?C2S_HIBERNATE_TIMEOUT};
fsm_next_state(wait_for_resume, #state{mgmt_timeout = 0} = StateData) ->
{stop, normal, StateData};
-fsm_next_state(wait_for_resume, StateData)
- when StateData#state.mgmt_state /= pending ->
+fsm_next_state(wait_for_resume, #state{mgmt_pending_since = undefined} =
+ StateData) ->
?INFO_MSG("Waiting for resumption of stream for ~s",
[jlib:jid_to_string(StateData#state.jid)]),
{next_state, wait_for_resume,