Permalink
Browse files

close connections explicitly when done with them

This is important for the PB client because it holds a socket open in a
gen_server.  The link from the webmachine resource to the
riakc_pb_socket is not enough to clean up when the resource finishes,
because it exits with Reason=normal in that case, so the riakc_pb_socket
gen_server lives on.

This adds wrc:disconnect/1, which closes the PB socket, but does nothing
for the HTTP client (since nothing is needed there).

The resources set the 'client' field of their context records or
'disconnected' after closing their client connections, in an effort to
help find bugs where code may try to use a client after it has been
closed.
  • Loading branch information...
1 parent d976801 commit bad1b78ac0c269b37f5c0f6e4f41fbff4bd81266 Bryan Fink committed Nov 24, 2010
@@ -68,6 +68,7 @@ get_version_summaries(ArticleKey) ->
[{link, <<"archive">>, '_', false},
%%%{reduce, {jsanon, time_order_fun()}, <<>>, false}, %TODO: paging
{map, {jsanon, summary_fun()}, <<>>, true}]),
+ wrc:disconnect(Client),
{ok, Results}.
%% code for summary map phase is in priv/mapred/summary_map.js
@@ -20,6 +20,7 @@
-module(session_resource).
-export([init/1,
+ finish_request/2,
allowed_methods/2,
expires/2,
resource_exists/2,
@@ -37,6 +38,10 @@ init([]) ->
{ok, Client} = wrc:connect(),
{ok, #ctx{client=Client}}.
+finish_request(RD, Ctx=#ctx{client=C}) ->
+ wrc:disconnect(C),
+ {true, RD, Ctx#ctx{client=disconnected}}.
+
allowed_methods(RD, Ctx) ->
{['HEAD','GET','DELETE'], RD, Ctx}.
@@ -162,7 +162,7 @@ process_post(RD, Ctx=#ctx{user=User, client=C}) ->
wriaki_auth:start_session(RD, User),
{ok, UC} = wrc:set_client_id(C, username(RD)),
wrc:put(UC, NewUser),
- {true, NewRD, NewUser};
+ {true, NewRD, Ctx#ctx{user=NewUser}};
false ->
{{halt, 409},
wrq:set_resp_header(
@@ -185,7 +185,9 @@ username(RD) ->
edit_mode(RD) ->
wrq:get_qs_value("edit", RD) /= undefined.
-finish_request(RD, Ctx) ->
+finish_request(RD, Ctx=#ctx{client=C}) ->
+ wrc:disconnect(C),
+ DCtx = Ctx#ctx{client=disconnected},
case wrq:response_code(RD) of
404 ->
{ok, Content} = user_404_dtl:render(
@@ -195,8 +197,8 @@ finish_request(RD, Ctx) ->
wrq:set_resp_header(
"Content-type", "text/html; charset=utf-8",
wrq:set_resp_body(Content, RD)),
- Ctx};
+ DCtx};
_ ->
- {true, RD, Ctx}
+ {true, RD, DCtx}
end.
@@ -223,13 +223,15 @@ finish_request(RD, Ctx) ->
true -> render_404_editor(RD, Ctx);
false -> render_404(RD, Ctx)
end,
+ wrc:disconnect(NewCtx#ctx.client),
{true,
wrq:set_resp_header(
"Content-type", "text/html; charset=utf-8",
wrq:set_resp_body(Content, NewRD)),
- NewCtx};
+ NewCtx#ctx{client=disconnected}};
_ ->
- {true, RD, Ctx}
+ wrc:disconnect(Ctx#ctx.client),
+ {true, RD, Ctx#ctx{client=disconnected}}
end.
render_404_editor(RD, Ctx) ->
View
@@ -22,6 +22,7 @@
-module(wrc).
-export([connect/0, connect/1,
+ disconnect/1,
ping/1,
get_client_id/1, set_client_id/2,
get_server_info/1,
@@ -79,6 +80,11 @@ connect_pb(ClientId, {IP, Port}) ->
{ok, #wrc{module = riakc_pb_socket,
client = C}}.
+disconnect(#wrc{module=riakc_pb_socket, client=C}) ->
+ riakc_pb_socket:stop(C);
+disconnect(_WRC) ->
+ ok.
+
ping(RC) ->
?PASS0(RC, ping).
@@ -30,7 +30,8 @@ set_bucket_props() ->
{ok, Client} = wrc:connect(),
ok = wrc:set_bucket(Client, ?B_ARTICLE,
[{allow_mult, true}|search_hook()]),
- ok = wrc:set_bucket(Client, ?B_HISTORY, [{allow_mult, true}]).
+ ok = wrc:set_bucket(Client, ?B_HISTORY, [{allow_mult, true}]),
+ wrc:disconnect(Client).
search_hook() ->
case search_enabled() of
@@ -39,7 +39,9 @@ check(RD) ->
check_user_pass(Username, Password) ->
{ok, Client} = wrc:connect(),
- case wrc:get(Client, ?B_USER, Username) of
+ LookupResult = wrc:get(Client, ?B_USER, Username),
+ wrc:disconnect(Client),
+ case LookupResult of
{ok, User} ->
case user_resource:password_matches(User, Password) of
true -> {ok, User};
@@ -58,11 +60,14 @@ check_cookie_auth(SessionCookie) ->
{ok, UC} = wrc:set_client_id(C, session:get_user(Session)),
wrc:put(UC, session:refresh(Session)),
{ok, User} = wuser:fetch(UC, session:get_user(Session)),
+ wrc:disconnect(UC),
{{cookie, SessionCookie}, User};
false ->
+ wrc:disconnect(C),
false
end;
{error, notfound} ->
+ wrc:disconnect(C),
false
end.
@@ -75,6 +80,7 @@ start_session(RD, User) ->
SessionCookie = wobj:key(Session),
{ok, C} = wrc:connect(Username),
ok = wrc:put(C, Session),
+ wrc:disconnect(C),
{wrq:merge_resp_headers(
[ mochiweb_cookies:cookie(K, V, [{path, "/"}])
|| {K, V} <- [{?USERNAME_COOKIE, Username},

0 comments on commit bad1b78

Please sign in to comment.