Browse Source

Handle socket error from tcp conn (#201)

If a socket error occurs when fetching a response, the mysql connection exits with the socket error as the exit reason instead of a crash.

Fixes #196.
Krishna Kumar Thokala 1 year ago
parent
commit
5b999ca8da
2 changed files with 9 additions and 13 deletions
  1. 4 8
      src/mysql_conn.erl
  2. 5 5
      src/mysql_protocol.erl

+ 4 - 8
src/mysql_conn.erl

@@ -596,10 +596,8 @@ execute_stmt(Stmt, Args, FilterMap, Timeout, State) ->
             kill_query(State),
             mysql_protocol:fetch_execute_response(SockMod, Socket,
                                                   [], FilterMap, ?cmd_timeout);
-        {error, timeout} ->
-            %% For MySQL 4.x.x there is no way to recover from timeout except
-            %% killing the connection itself.
-            exit(timeout);
+        {error, Reason} ->
+            exit(Reason);
         QueryResult ->
             QueryResult
     end,
@@ -657,10 +655,8 @@ query(Query, FilterMap, Timeout, State) ->
             mysql_protocol:fetch_query_response(SockMod, Socket,
                                                 [], FilterMap,
                                                 ?cmd_timeout);
-        {error, timeout} ->
-            %% For MySQL 4.x.x there is no way to recover from timeout except
-            %% killing the connection itself.
-            exit(timeout);
+        {error, Reason} ->
+            exit(Reason);
         QueryResult ->
             QueryResult
     end,

+ 5 - 5
src/mysql_protocol.erl

@@ -195,7 +195,7 @@ ping(SockModule, Socket) ->
 
 -spec query(Query :: iodata(), module(), term(), [binary()], query_filtermap(),
             timeout()) ->
-    {ok, [#ok{} | #resultset{} | #error{}]} | {error, timeout}.
+    {ok, [#ok{} | #resultset{} | #error{}]} | {error, term()}.
 query(Query, SockModule, Socket, AllowedPaths, FilterMap, Timeout) ->
     Req = <<?COM_QUERY, (iolist_to_binary(Query))/binary>>,
     SeqNum0 = 0,
@@ -252,7 +252,7 @@ unprepare(#prepared{statement_id = Id}, SockModule, Socket) ->
 %% @doc Executes a prepared statement.
 -spec execute(#prepared{}, [term()], module(), term(), [binary()],
               query_filtermap(), timeout()) ->
-    {ok, [#ok{} | #resultset{} | #error{}]} | {error, timeout}.
+    {ok, [#ok{} | #resultset{} | #error{}]} | {error, term()}.
 execute(#prepared{statement_id = Id, param_count = ParamCount}, ParamValues,
         SockModule, Socket, AllowedPaths, FilterMap, Timeout)
   when ParamCount == length(ParamValues) ->
@@ -590,7 +590,7 @@ parse_handshake_confirm(<<?MORE_DATA, MoreData/binary>>) ->
 %% prepared statements).
 -spec fetch_response(module(), term(), timeout(), text | binary, [binary()],
                      query_filtermap(), list()) ->
-    {ok, [#ok{} | #resultset{} | #error{}]} | {error, timeout}.
+    {ok, [#ok{} | #resultset{} | #error{}]} | {error, term()}.
 fetch_response(SockModule, Socket, Timeout, Proto, AllowedPaths, FilterMap, Acc) ->
     case recv_packet(SockModule, Socket, Timeout, any) of
         {ok, ?local_infile_pattern = Packet, SeqNum2} ->
@@ -631,8 +631,8 @@ fetch_response(SockModule, Socket, Timeout, Proto, AllowedPaths, FilterMap, Acc)
                 false ->
                     {ok, lists:reverse(Acc1)}
             end;
-        {error, timeout} ->
-            {error, timeout}
+        {error, Reason} ->
+            {error, Reason}
     end.
 
 %% @doc Fetches a result set.