summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shulga <Dmitry.Shulga@Sun.COM>2010-07-21 14:56:43 +0700
committerDmitry Shulga <Dmitry.Shulga@Sun.COM>2010-07-21 14:56:43 +0700
commitbd41af86ebc53510760504b980f073be4438f6e9 (patch)
tree6fa561732c7d7b6aafd747e41417467da3cab2c9
parent7ccbf9b817b47d0393fe66bda6f6013ec24486ba (diff)
downloadmariadb-git-bd41af86ebc53510760504b980f073be4438f6e9.tar.gz
Fixed bug #42496 - the server could crash on a debug assert after a failure
to write into a closed socket sql/protocol.cc: Protocol::flush modified: set thd->main_da.can_overwrite_status= TRUE before call to net_flush() in order to prevent crash on assert in case of socket write failure, reset it to FALSE when net_flush() returned; Protocol::send_fields modified: return from method with error if call to my_net_write(), proto.write() or write_eof_packet() failed. sql/sql_cache.cc: Query_cache::send_result_to_client modified: call to thd->main_da.disable_status() only if write to socket was successful. sql/sql_cursor.cc: Materialized_cursor::fetch modified: leave method if call to result->send_data() failed. sql/sql_prepare.cc: send_prep_stmt() modified: call to thd->main_da.disable_status() only if thd->protocol_text.send_fields() completed successfully.
-rw-r--r--sql/protocol.cc15
-rw-r--r--sql/sql_cache.cc3
-rw-r--r--sql/sql_cursor.cc7
-rw-r--r--sql/sql_prepare.cc7
4 files changed, 24 insertions, 8 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc
index dc53e029647..dfb78462f13 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -534,7 +534,11 @@ void Protocol::end_partial_result_set(THD *thd_arg)
bool Protocol::flush()
{
#ifndef EMBEDDED_LIBRARY
- return net_flush(&thd->net);
+ bool error;
+ thd->main_da.can_overwrite_status= TRUE;
+ error= net_flush(&thd->net);
+ thd->main_da.can_overwrite_status= FALSE;
+ return error;
#else
return 0;
#endif
@@ -574,7 +578,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
uchar *pos= net_store_length(buff, list->elements);
- (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
+ if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
+ DBUG_RETURN(1);
}
#ifndef DBUG_OFF
@@ -698,7 +703,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_DEFAULTS)
item->send(&prot, &tmp); // Send default value
if (prot.write())
- break; /* purecov: inspected */
+ DBUG_RETURN(1);
#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
@@ -711,7 +716,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
- write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
+ if (write_eof_packet(thd, &thd->net, thd->server_status,
+ thd->total_warn_count))
+ DBUG_RETURN(1);
}
DBUG_RETURN(prepare_for_send(list));
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index f862cbed4f1..fcf4edbdc22 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1653,7 +1653,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
- thd->main_da.disable_status();
+ if (!thd->main_da.is_set())
+ thd->main_da.disable_status();
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(1); // Result sent to client
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 6f61dc40f66..d7d029d28d4 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -658,7 +658,12 @@ void Materialized_cursor::fetch(ulong num_rows)
if ((res= table->file->rnd_next(table->record[0])))
break;
/* Send data only if the read was successful. */
- result->send_data(item_list);
+ /*
+ If network write failed (i.e. due to a closed socked),
+ the error has already been set. Just return.
+ */
+ if (result->send_data(item_list))
+ return;
}
switch (res) {
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 041d9f7c30b..bd152866deb 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -263,8 +263,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
- /* Flag that a response has already been sent */
- thd->main_da.disable_status();
+
+ if (!error)
+ /* Flag that a response has already been sent */
+ thd->main_da.disable_status();
+
DBUG_RETURN(error);
}
#else