aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Fedotov <[email protected]>2016-05-03 13:28:09 +0100
committerDaniil Fedotov <[email protected]>2016-05-05 09:41:35 +0100
commit33b282356b786b831fe8f5414fa60397c4c7eaf9 (patch)
tree3a4dd0ad35248b88f8d26468c9e89ab83a83ec67
parent6a1290f534164d1a5771dba37c23124652b9f7c9 (diff)
downloadotp-33b282356b786b831fe8f5414fa60397c4c7eaf9.tar.gz
otp-33b282356b786b831fe8f5414fa60397c4c7eaf9.tar.bz2
otp-33b282356b786b831fe8f5414fa60397c4c7eaf9.zip
Ignore tcp errors during close request to eldap
If underlying tcp connection is closed and LDAP operation returned tcp error, then client applications tend to close ldap handle with eldap:close. This will cause do_unbind to throw gen_tcp_error, which is unhandled and will be sent to linked process as {nocatch, {gen_tcp_error, ...}}. eldap should ignore gen_tcp_error during close, because it will be closing anyway.
-rw-r--r--lib/eldap/src/eldap.erl7
-rw-r--r--lib/eldap/test/eldap_basic_SUITE.erl27
2 files changed, 32 insertions, 2 deletions
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index dc236f8a44..8994df10eb 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -564,7 +564,12 @@ loop(Cpid, Data) ->
?MODULE:loop(Cpid, NewData);
{_From, close} ->
- {no_reply,_NewData} = do_unbind(Data),
+ % Ignore tcp error if connection is already closed.
+ try do_unbind(Data) of
+ {no_reply,_NewData} -> ok
+ catch
+ throw:{gen_tcp_error, _TcpErr} -> ok
+ end,
unlink(Cpid),
exit(closed);
diff --git a/lib/eldap/test/eldap_basic_SUITE.erl b/lib/eldap/test/eldap_basic_SUITE.erl
index 9a23f74e22..536e891a1e 100644
--- a/lib/eldap/test/eldap_basic_SUITE.erl
+++ b/lib/eldap/test/eldap_basic_SUITE.erl
@@ -94,7 +94,8 @@ connection_tests() ->
client_side_start_tls_timeout,
client_side_bind_timeout,
client_side_add_timeout,
- client_side_search_timeout
+ client_side_search_timeout,
+ close_after_tcp_error
].
@@ -312,6 +313,30 @@ tcp_connection(Config) ->
end.
%%%----------------------------------------------------------------
+
+close_after_tcp_error(Config) ->
+ Host = proplists:get_value(listen_host, Config),
+ Port = proplists:get_value(listen_port, Config),
+ Opts = proplists:get_value(tcp_connect_opts, Config),
+ T = 1000,
+ case eldap:open([Host], [{timeout,T},{port,Port}|Opts]) of
+ {ok,H} ->
+ Sl = proplists:get_value(listen_socket, Config),
+ gen_tcp:close(Sl),
+ {error,{gen_tcp_error,closed}} = eldap:simple_bind(H, anon, anon),
+ ok = eldap:close(H),
+ wait_for_close(H);
+ Other -> ct:fail("eldap:open failed: ~p",[Other])
+ end.
+
+wait_for_close(H) ->
+ case erlang:is_process_alive(H) of
+ true -> timer:sleep(100),
+ wait_for_close(H);
+ false -> ok
+ end.
+
+%%%----------------------------------------------------------------
ssl_connection(Config) ->
Host = proplists:get_value(listen_host, Config),
Port = proplists:get_value(ssl_listen_port, Config),