diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
commit | a2a2e32c02643a0cec111511220227703fda1cd5 (patch) | |
tree | 69cc2b631234c2a8e026b9cd4d72676c61c594df /sql/net_serv.cc | |
parent | Releasing progress-linux version 1:10.11.8-1~progress7.99u1. (diff) | |
download | mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.tar.xz mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.zip |
Merging upstream version 1:11.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | sql/net_serv.cc | 540 |
1 files changed, 140 insertions, 400 deletions
diff --git a/sql/net_serv.cc b/sql/net_serv.cc index af65d92c..d8bfc8d3 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -47,6 +47,8 @@ #include "probes_mysql.h" #include <debug_sync.h> #include "proxy_protocol.h" +#include <mysql_com_server.h> +#include <mysqld.h> PSI_memory_key key_memory_NET_buff; PSI_memory_key key_memory_NET_compress_packet; @@ -62,13 +64,9 @@ PSI_memory_key key_memory_NET_compress_packet; */ #ifdef EXTRA_DEBUG #define EXTRA_DEBUG_fprintf fprintf -#define EXTRA_DEBUG_fflush fflush #define EXTRA_DEBUG_ASSERT DBUG_ASSERT #else static void inline EXTRA_DEBUG_fprintf(...) {} -#ifndef MYSQL_SERVER -static int inline EXTRA_DEBUG_fflush(...) { return 0; } -#endif #endif /* EXTRA_DEBUG */ #ifdef MYSQL_SERVER @@ -98,22 +96,6 @@ static void inline MYSQL_SERVER_my_error(...) {} the client should have a bigger max_allowed_packet. */ -#if defined(_WIN32) || !defined(MYSQL_SERVER) - /* The following is because alarms doesn't work on windows. */ -#ifndef NO_ALARM -#define NO_ALARM -#endif -#endif - -#ifndef NO_ALARM -#include "my_pthread.h" -void sql_print_error(const char *format,...); -#else -#define DONT_USE_THR_ALARM -#endif /* NO_ALARM */ - -#include "thr_alarm.h" - #ifdef MYSQL_SERVER /* The following variables/functions should really not be declared @@ -166,22 +148,18 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) net->using_proxy_protocol= 0; net->thread_specific_malloc= MY_TEST(my_flags & MY_THREAD_SPECIFIC); net->thd= 0; -#ifdef MYSQL_SERVER net->extension= NULL; net->thd= thd; -#endif if (vio) { /* For perl DBI/DBD. */ net->fd= vio_fd(vio); -#if defined(MYSQL_SERVER) && !defined(_WIN32) if (!(test_flags & TEST_BLOCKING)) { my_bool old_mode; vio_blocking(vio, FALSE, &old_mode); } -#endif vio_fastsend(vio); } DBUG_RETURN(0); @@ -655,12 +633,7 @@ net_real_write(NET *net,const uchar *packet, size_t len) { size_t length; const uchar *pos,*end; - thr_alarm_t alarmed; -#ifndef NO_ALARM - ALARM alarm_buff; -#endif uint retry_count=0; - my_bool net_blocking = vio_is_blocking(net->vio); DBUG_ENTER("net_real_write"); #if defined(MYSQL_SERVER) @@ -716,62 +689,21 @@ net_real_write(NET *net,const uchar *packet, size_t len) #ifdef DEBUG_DATA_PACKETS DBUG_DUMP("data_written", packet, len); #endif - -#ifndef NO_ALARM - thr_alarm_init(&alarmed); - if (net_blocking) - thr_alarm(&alarmed, net->write_timeout, &alarm_buff); -#else - alarmed=0; - /* Write timeout is set in my_net_set_write_timeout */ -#endif /* NO_ALARM */ - pos= packet; end=pos+len; while (pos != end) { - if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0) + length= vio_write(net->vio, pos, (size_t) (end - pos)); + if (ssize_t(length) <= 0) { - my_bool interrupted = vio_should_retry(net->vio); -#if !defined(_WIN32) - if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed)) + bool interrupted= vio_should_retry(net->vio); + if (interrupted || !length) { - if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff)) - { /* Always true for client */ - my_bool old_mode; - while (vio_blocking(net->vio, TRUE, &old_mode) < 0) - { - if (vio_should_retry(net->vio) && retry_count++ < net->retry_count) - continue; - EXTRA_DEBUG_fprintf(stderr, - "%s: my_net_write: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); - net->error= 2; /* Close socket */ - net->last_errno= ER_NET_PACKET_TOO_LARGE; - MYSQL_SERVER_my_error(ER_NET_PACKET_TOO_LARGE, MYF(0)); - goto end; - } - retry_count=0; - continue; - } + if (retry_count++ < net->retry_count) + continue; } - else -#endif /* !defined(_WIN32) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { - if (retry_count++ < net->retry_count) - continue; - EXTRA_DEBUG_fprintf(stderr, "%s: write looped, aborting thread\n", - my_progname); - } -#ifndef MYSQL_SERVER - if (vio_errno(net->vio) == SOCKET_EINTR) - { - DBUG_PRINT("warning",("Interrupted write. Retrying...")); - continue; - } -#endif /* !defined(MYSQL_SERVER) */ + EXTRA_DEBUG_fprintf(stderr, "%s: write looped, aborting thread\n", + my_progname); net->error= 2; /* Close socket */ net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : ER_NET_ERROR_ON_WRITE); @@ -793,113 +725,15 @@ net_real_write(NET *net,const uchar *packet, size_t len) pos+=length; update_statistics(thd_increment_bytes_sent(net->thd, length)); } -#ifndef _WIN32 - end: -#endif #ifdef HAVE_COMPRESS if (net->compress) my_free((void*) packet); #endif - if (thr_alarm_in_use(&alarmed)) - { - my_bool old_mode; - thr_end_alarm(&alarmed); - if (!net_blocking) - vio_blocking(net->vio, net_blocking, &old_mode); - } - net->reading_or_writing=0; - DBUG_RETURN(((int) (pos != end))); -} - - -/***************************************************************************** -** Read something from server/clinet -*****************************************************************************/ - -#ifndef NO_ALARM - -static my_bool net_safe_read(NET *net, uchar *buff, size_t length, - thr_alarm_t *alarmed) -{ - uint retry_count=0; - while (length > 0) - { - size_t tmp; - if ((long) (tmp= vio_read(net->vio, buff, length)) <= 0) - { - my_bool interrupted = vio_should_retry(net->vio); - if (!thr_got_alarm(alarmed) && interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < net->retry_count) - continue; - } - return 1; - } - length-= tmp; - buff+= tmp; - } - return 0; + net->reading_or_writing= 0; + DBUG_RETURN(pos != end); } /** - Help function to clear the commuication buffer when we get a too big packet. - - @param net Communication handle - @param remain Bytes to read - @param alarmed Parameter for thr_alarm() - @param alarm_buff Parameter for thr_alarm() - - @retval - 0 Was able to read the whole packet - @retval - 1 Got mailformed packet from client -*/ - -static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, - ALARM *alarm_buff) -{ - longlong limit= net->max_packet_size*net->net_skip_rest_factor; - uint32 old=remain; - DBUG_ENTER("my_net_skip_rest"); - DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain)); - - /* The following is good for debugging */ - update_statistics(thd_increment_net_big_packet_count(net->thd, 1)); - - if (!thr_alarm_in_use(alarmed)) - { - my_bool old_mode; - if (thr_alarm(alarmed,net->read_timeout, alarm_buff) || - vio_blocking(net->vio, TRUE, &old_mode) < 0) - DBUG_RETURN(1); /* Can't setup, abort */ - } - for (;;) - { - while (remain > 0) - { - size_t length= MY_MIN(remain, net->max_packet); - if (net_safe_read(net, net->buff, length, alarmed)) - DBUG_RETURN(1); - update_statistics(thd_increment_bytes_received(net->thd, length)); - remain -= (uint32) length; - limit-= length; - if (limit < 0) - DBUG_RETURN(1); - } - if (old != MAX_PACKET_LENGTH) - break; - if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed)) - DBUG_RETURN(1); - limit-= NET_HEADER_SIZE; - old=remain= uint3korr(net->buff); - net->pkt_nr++; - } - DBUG_RETURN(0); -} -#endif /* NO_ALARM */ - - -/** Try to parse and process proxy protocol header. This function is called in case MySQL packet header cannot be parsed. @@ -973,26 +807,18 @@ static handle_proxy_header_result handle_proxy_header(NET *net) Returns length of packet. */ -static ulong -my_real_read(NET *net, size_t *complen, - my_bool header __attribute__((unused))) +static ulong my_real_read(NET *net, size_t *complen, + my_bool header __attribute__((unused))) { uchar *pos; size_t length; uint i,retry_count=0; ulong len=packet_error; my_bool expect_error_packet __attribute__((unused))= 0; - thr_alarm_t alarmed; -#ifndef NO_ALARM - ALARM alarm_buff; -#endif - retry: - my_bool net_blocking=vio_is_blocking(net->vio); uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : NET_HEADER_SIZE); -#ifdef MYSQL_SERVER size_t count= remain; struct st_net_server *server_extension= 0; @@ -1005,99 +831,41 @@ retry: server_extension->m_before_header(net, user_data, count); } } -#endif *complen = 0; net->reading_or_writing=1; - thr_alarm_init(&alarmed); -#ifndef NO_ALARM - if (net_blocking) - thr_alarm(&alarmed,net->read_timeout,&alarm_buff); -#else - /* Read timeout is set in my_net_set_read_timeout */ -#endif /* NO_ALARM */ - - pos = net->buff + net->where_b; /* net->packet -4 */ - for (i=0 ; i < 2 ; i++) + pos = net->buff + net->where_b; + for (i=0; i < 2 ; i++) + { + while (remain > 0) { - while (remain > 0) + length= vio_read(net->vio, pos, remain); + if ((ssize_t) length <= 0) { - /* First read is done with non blocking mode */ - if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L) + DBUG_PRINT("info", ("vio_read returned %lld errno: %d", + (long long) length, vio_errno(net->vio))); + if (i == 0 && unlikely(thd_net_is_killed((THD *) net->thd))) { - my_bool interrupted = vio_should_retry(net->vio); - - DBUG_PRINT("info",("vio_read returned %ld errno: %d", - (long) length, vio_errno(net->vio))); - - if (i== 0 && unlikely(thd_net_is_killed((THD*) net->thd))) - { - DBUG_PRINT("info", ("thd is killed")); - len= packet_error; - net->error= 0; - net->last_errno= ER_CONNECTION_KILLED; - MYSQL_SERVER_my_error(net->last_errno, MYF(0)); - goto end; - } - -#if !defined(_WIN32) && defined(MYSQL_SERVER) - /* - We got an error that there was no data on the socket. We now set up - an alarm to not 'read forever', change the socket to the blocking - mode and try again - */ - if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed)) - { - if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */ - { - my_bool old_mode; - while (vio_blocking(net->vio, TRUE, &old_mode) < 0) - { - if (vio_should_retry(net->vio) && - retry_count++ < net->retry_count) - continue; - DBUG_PRINT("error", - ("fcntl returned error %d, aborting thread", - vio_errno(net->vio))); - EXTRA_DEBUG_fprintf(stderr, - "%s: read: fcntl returned error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); - len= packet_error; - net->error= 2; /* Close socket */ - net->last_errno= ER_NET_FCNTL_ERROR; - MYSQL_SERVER_my_error(ER_NET_FCNTL_ERROR, MYF(0)); - goto end; - } - retry_count=0; - continue; - } - } -#endif /* (!defined(_WIN32) && defined(MYSQL_SERVER) */ - if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) && - interrupted) - { /* Probably in MIT threads */ - if (retry_count++ < net->retry_count) - continue; - EXTRA_DEBUG_fprintf(stderr, "%s: read looped with error %d on " - "file %lld, aborting thread\n", - my_progname, vio_errno(net->vio), - (longlong) vio_fd(net->vio)); - } -#ifndef MYSQL_SERVER - if (length != 0 && vio_should_retry(net->vio)) - { - DBUG_PRINT("warning",("Interrupted read. Retrying...")); - continue; - } -#endif - DBUG_PRINT("error",("Could not read packet: remain: %u errno: %d length: %ld", - remain, vio_errno(net->vio), (long) length)); - len= packet_error; - net->error= 2; /* Close socket */ - net->last_errno= (vio_was_timeout(net->vio) ? - ER_NET_READ_INTERRUPTED : - ER_NET_READ_ERROR); + DBUG_PRINT("info", ("thd is killed")); + len= packet_error; + net->error= 0; + net->last_errno= ER_CONNECTION_KILLED; + MYSQL_SERVER_my_error(net->last_errno, MYF(0)); + goto end; + } + if (vio_should_retry(net->vio) && retry_count++ < net->retry_count) + continue; + EXTRA_DEBUG_fprintf(stderr, + "%s: read looped with error %d, aborting thread\n", + my_progname, vio_errno(net->vio)); + DBUG_PRINT("error", + ("Couldn't read packet: remain: %u errno: %d length: %ld", + remain, vio_errno(net->vio), (long) length)); + len= packet_error; + net->error= 2; + net->last_errno= (vio_was_timeout(net->vio) ? ER_NET_READ_INTERRUPTED + : ER_NET_READ_ERROR); #ifdef MYSQL_SERVER if (global_system_variables.log_warnings > 3) { @@ -1113,174 +881,146 @@ retry: else my_error(net->last_errno, MYF(0)); #endif /* MYSQL_SERVER */ - goto end; - } - remain -= (uint32) length; - pos+= length; - update_statistics(thd_increment_bytes_received(net->thd, length)); + goto end; } - + remain-= (uint32) length; + pos+= length; + update_statistics(thd_increment_bytes_received(net->thd, length)); + } #ifdef DEBUG_DATA_PACKETS - DBUG_DUMP("data_read", net->buff+net->where_b, length); + DBUG_DUMP("data_read", net->buff + net->where_b, length); #endif - if (i == 0) - { /* First parts is packet length */ - size_t helping; + if (i == 0) + { + /* First part is packet length */ + size_t helping; #ifndef DEBUG_DATA_PACKETS - DBUG_DUMP("packet_header", net->buff+net->where_b, - NET_HEADER_SIZE); + DBUG_DUMP("packet_header", net->buff + net->where_b, NET_HEADER_SIZE); #endif - if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) + if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) + { + if (net->pkt_nr_can_be_reset) + { + /* + We are using a protocol like semi-sync where master and slave + sends packets in parallel. + Copy current one as it can be useful for debugging. + */ + net->pkt_nr= net->buff[net->where_b + 3]; + } + else { - if (net->pkt_nr_can_be_reset) +#ifndef MYSQL_SERVER + if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1)) { /* - We are using a protocol like semi-sync where master and slave - sends packets in parallel. - Copy current one as it can be useful for debugging. + If the server was killed then the server may have missed the + last sent client packet and the packet numbering may be one off. */ - net->pkt_nr= net->buff[net->where_b + 3]; + DBUG_PRINT("warning", ("Found possible out of order packets")); + expect_error_packet= 1; } else - { -#ifndef MYSQL_SERVER - if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1)) - { - /* - If the server was killed then the server may have missed the - last sent client packet and the packet numbering may be one off. - */ - DBUG_PRINT("warning", ("Found possible out of order packets")); - expect_error_packet= 1; - } - else #endif - goto packets_out_of_order; - } + goto packets_out_of_order; } - net->compress_pkt_nr= ++net->pkt_nr; + } + net->compress_pkt_nr= ++net->pkt_nr; #ifdef HAVE_COMPRESS - if (net->compress) - { - /* - The following uint3korr() may read 4 bytes, so make sure we don't - read unallocated or uninitialized memory. The right-hand expression - must match the size of the buffer allocated in net_realloc(). - */ - DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <= - net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1); - /* - If the packet is compressed then complen > 0 and contains the - number of bytes in the uncompressed packet - */ - *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE])); - } + if (net->compress) + { + /* + The following uint3korr() may read 4 bytes, so make sure we don't + read unallocated or uninitialized memory. The right-hand expression + must match the size of the buffer allocated in net_realloc(). + */ + DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <= + net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1); + /* + If the packet is compressed then complen > 0 and contains the + number of bytes in the uncompressed packet + */ + *complen= uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE])); + } #endif - len=uint3korr(net->buff+net->where_b); - if (!len) /* End of big multi-packet */ - goto end; - helping = MY_MAX(len,*complen) + net->where_b; - /* The necessary size of net->buff */ - if (helping >= net->max_packet) - { - if (net_realloc(net,helping)) - { -#if defined(MYSQL_SERVER) && !defined(NO_ALARM) - if (!net->compress && - !my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff)) - net->error= 3; /* Successfully skiped packet */ -#endif - len= packet_error; /* Return error and close connection */ - goto end; - } - } - pos=net->buff + net->where_b; - remain = (uint32) len; -#ifdef MYSQL_SERVER - if (server_extension != NULL) + len= uint3korr(net->buff + net->where_b); + if (!len) /* End of big multi-packet */ + goto end; + helping= MY_MAX(len, *complen) + net->where_b; + /* The necessary size of net->buff */ + if (helping >= net->max_packet) + { + if (net_realloc(net, helping)) { - void *user_data= server_extension->m_user_data; - server_extension->m_after_header(net, user_data, count, 0); - server_extension= NULL; + len= packet_error; /* Return error and close connection */ + goto end; } -#endif } + pos= net->buff + net->where_b; + remain= (uint32) len; + if (server_extension != NULL) + { + void *user_data= server_extension->m_user_data; + server_extension->m_after_header(net, user_data, count, 0); + server_extension= NULL; + } + } #ifndef MYSQL_SERVER - else if (expect_error_packet) + else if (expect_error_packet) + { + /* + This check is safe both for compressed and not compressed protocol + as for the compressed protocol errors are not compressed anymore. + */ + if (net->buff[net->where_b] != (uchar) 255) { - /* - This check is safe both for compressed and not compressed protocol - as for the compressed protocol errors are not compressed anymore. - */ - if (net->buff[net->where_b] != (uchar) 255) - { - /* Restore pkt_nr to original value */ - net->pkt_nr--; - goto packets_out_of_order; - } + /* Restore pkt_nr to original value */ + net->pkt_nr--; + goto packets_out_of_order; } -#endif } +#endif + } end: - if (thr_alarm_in_use(&alarmed)) - { - my_bool old_mode; - thr_end_alarm(&alarmed); - if (!net_blocking) - vio_blocking(net->vio, net_blocking, &old_mode); - } net->reading_or_writing=0; #ifdef DEBUG_DATA_PACKETS if (len != packet_error) DBUG_DUMP("data_read", net->buff+net->where_b, len); #endif -#ifdef MYSQL_SERVER if (server_extension != NULL) { void *user_data= server_extension->m_user_data; server_extension->m_after_header(net, user_data, count, 1); DBUG_ASSERT(len == packet_error || len == 0); } -#endif return(len); -packets_out_of_order: +packets_out_of_order : + switch (handle_proxy_header(net)) { - switch (handle_proxy_header(net)) { - case ABORT: - /* error happened, message is already written. */ - len= packet_error; - goto end; - case RETRY: - goto retry; - case IGNORE: - break; - } - - DBUG_PRINT("error", - ("Packets out of order (Found: %d, expected %u)", - (int) net->buff[net->where_b + 3], - net->pkt_nr)); - EXTRA_DEBUG_ASSERT(0); - /* - We don't make noise server side, since the client is expected - to break the protocol for e.g. --send LOAD DATA .. LOCAL where - the server expects the client to send a file, but the client - may reply with a new command instead. - */ -#ifndef MYSQL_SERVER - EXTRA_DEBUG_fflush(stdout); - EXTRA_DEBUG_fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n", - (int) net->buff[net->where_b + 3], - (uint) (uchar) net->pkt_nr); - EXTRA_DEBUG_fflush(stderr); -#endif + case ABORT: + /* error happened, message is already written. */ len= packet_error; - MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0)); goto end; + case RETRY: + goto retry; + case IGNORE: + break; } + DBUG_PRINT("error", ("Packets out of order (Found: %d, expected %u)", + (int) net->buff[net->where_b + 3], net->pkt_nr)); + EXTRA_DEBUG_ASSERT(0); + /* + We don't make noise server side, since the client is expected + to break the protocol for e.g. --send LOAD DATA .. LOCAL where + the server expects the client to send a file, but the client + may reply with a new command instead. + */ + len= packet_error; + MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0)); + goto end; } |