From: ahmad.abdullateef Date: January 2 2013 8:26am Subject: bzr push into mysql-trunk branch (ahmad.abdullateef:5313 to 5314) Bug#13934876 List-Archive: http://lists.mysql.com/commits/145559 X-Bug: 13934876 Message-Id: <20130102082604.5136.488.5314@AHABDULL-IN.idc.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 5314 Ahmad Abdullateef 2013-01-02 [merge] BUG#13934876 - SHARED MEMORY CONNECTIONS CRASH THE SERVER WHEN ENDING DESCRIPTION: When mysqld is in shared memory mode under windows and we stress test the server with a multi threaded client which also randomly issues "kill connection" command we see the mysqld process crashing randomly. ANALYSIS : When "kill connection xx" is received and executed on an arbitrary thread it calls THD::shutdown_active_vio() on the THD refered to by connection xx, this results in the shared memory being unmapped. However the original thread serving the connection xx might be in middle of a vio_read or vio_write and it might end up accessing the unmapped region of memory resulting in a crash. FIX : When "kill connection xx" is executed on an arbitrary thread it calls THD::shutdown_active_vio() on the THD referred to by xx, this results in the shared memory being unmapped. However the thread serving the connection xx might be in middle of a vio_read or vio_write and it might end up accessing the unmapped region of memory. All handles are closed and the VIO is cleaned up when vio_delete() is called and this completes the vio cleanup operation in its entirety. All references to vio_close has been changed to vio_shutdown to cleanup code and make its meaning relevant. modified: config.h.cmake configure.cmake include/violite.h sql/rpl_slave.cc sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_prepare.cc vio/vio.c vio/vio_priv.h vio/viopipe.c vio/vioshm.c vio/viosocket.c vio/viossl.c 5313 Ahmad Abdullateef 2013-01-02 [merge] BUG#14792410 - INCONSISTENCY ABOUT MESSAGEFILE PATH NAME STYLE IN MTR ON ALL PLATFORMS DESCRIPTION: Errors are printed in the Server logs when a directory containg errmsg.sys is specified directly through the --lc-messages-dir or --language parameter. FIX : Improved the messaging and changed sql_print_error() to sql_print_warning(). modified: sql/derror.cc === modified file 'config.h.cmake' --- a/config.h.cmake 2012-12-18 08:54:05 +0000 +++ b/config.h.cmake 2013-01-02 08:09:22 +0000 @@ -495,7 +495,7 @@ #define MACHINE_TYPE "@MYSQL_MACHINE_TYPE@" #cmakedefine HAVE_DTRACE 1 -#cmakedefine SIGNAL_WITH_VIO_CLOSE 1 +#cmakedefine SIGNAL_WITH_VIO_SHUTDOWN 1 /* Windows stuff, mostly functions, that have Posix analogs but named differently */ #cmakedefine S_IROTH @S_IROTH@ === modified file 'configure.cmake' --- a/configure.cmake 2012-11-23 13:12:26 +0000 +++ b/configure.cmake 2013-01-02 08:09:22 +0000 @@ -55,7 +55,7 @@ ENDIF() # As a consequence of ALARMs no longer being used, thread # notification for KILL must close the socket to wake up # other threads. -SET(SIGNAL_WITH_VIO_CLOSE 1) +SET(SIGNAL_WITH_VIO_SHUTDOWN 1) # Always enable -Wall for gnu C/C++ IF(CMAKE_COMPILER_IS_GNUCXX) === modified file 'include/violite.h' --- a/include/violite.h 2012-11-06 09:20:51 +0000 +++ b/include/violite.h 2013-01-02 08:09:22 +0000 @@ -37,8 +37,8 @@ typedef struct st_vio Vio; enum enum_vio_type { - VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, - VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY + VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL, + VIO_TYPE_SHARED_MEMORY }; /** @@ -71,19 +71,19 @@ Vio* vio_new_win32shared_memory(HANDLE h #define HANDLE void * #endif /* __WIN__ */ -void vio_delete(Vio* vio); -int vio_close(Vio* vio); +void vio_delete(Vio* vio); +int vio_shutdown(Vio* vio); my_bool vio_reset(Vio* vio, enum enum_vio_type type, my_socket sd, void *ssl, uint flags); -size_t vio_read(Vio *vio, uchar * buf, size_t size); +size_t vio_read(Vio *vio, uchar * buf, size_t size); size_t vio_read_buff(Vio *vio, uchar * buf, size_t size); -size_t vio_write(Vio *vio, const uchar * buf, size_t size); +size_t vio_write(Vio *vio, const uchar * buf, size_t size); /* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */ -int vio_fastsend(Vio *vio); +int vio_fastsend(Vio *vio); /* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */ -int vio_keepalive(Vio *vio, my_bool onoff); +int vio_keepalive(Vio *vio, my_bool onoff); /* Whenever we should retry the last read/write operation. */ -my_bool vio_should_retry(Vio *vio); +my_bool vio_should_retry(Vio *vio); /* Check that operation was timed out */ my_bool vio_was_timeout(Vio *vio); /* Short text description of the socket for those, who are curious.. */ @@ -161,13 +161,13 @@ int sslconnect(struct st_VioSSLFd*, Vio struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, - const char *ca_file, const char *ca_path, - const char *cipher, enum enum_ssl_init_error *error, + const char *ca_file, const char *ca_path, + const char *cipher, enum enum_ssl_init_error *error, const char *crl_file, const char *crl_path); struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, - const char *ca_file,const char *ca_path, - const char *cipher, enum enum_ssl_init_error *error, + const char *ca_file,const char *ca_path, + const char *cipher, enum enum_ssl_init_error *error, const char *crl_file, const char *crl_path); void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); #endif /* ! EMBEDDED_LIBRARY */ @@ -175,21 +175,21 @@ void free_vio_ssl_acceptor_fd(struct st_ void vio_end(void); -#ifdef __cplusplus +#ifdef __cplusplus } #endif #if !defined(DONT_MAP_VIO) -#define vio_delete(vio) (vio)->viodelete(vio) -#define vio_errno(vio) (vio)->vioerrno(vio) +#define vio_delete(vio) (vio)->viodelete(vio) +#define vio_errno(vio) (vio)->vioerrno(vio) #define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size) #define vio_write(vio, buf, size) ((vio)->write)(vio, buf, size) -#define vio_fastsend(vio) (vio)->fastsend(vio) -#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) -#define vio_should_retry(vio) (vio)->should_retry(vio) +#define vio_fastsend(vio) (vio)->fastsend(vio) +#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) +#define vio_should_retry(vio) (vio)->should_retry(vio) #define vio_was_timeout(vio) (vio)->was_timeout(vio) -#define vio_close(vio) ((vio)->vioclose)(vio) -#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) +#define vio_shutdown(vio) ((vio)->vioshutdown)(vio) +#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) #define vio_io_wait(vio, event, timeout) (vio)->io_wait(vio, event, timeout) #define vio_is_connected(vio) (vio)->is_connected(vio) #endif /* !defined(DONT_MAP_VIO) */ @@ -209,13 +209,14 @@ enum SSL_type /* This structure is for every connection on both sides */ struct st_vio { - MYSQL_SOCKET mysql_socket; /* Instrumented socket */ - my_bool localhost; /* Are we from localhost? */ - struct sockaddr_storage local; /* Local internet address */ - struct sockaddr_storage remote; /* Remote internet address */ + MYSQL_SOCKET mysql_socket; /* Instrumented socket */ + my_bool localhost; /* Are we from localhost? */ + struct sockaddr_storage local; /* Local internet address */ + struct sockaddr_storage remote; /* Remote internet address */ int addrLen; /* Length of remote address */ - enum enum_vio_type type; /* Type of connection */ - char desc[VIO_DESCRIPTION_SIZE]; /* Description string. This + enum enum_vio_type type; /* Type of connection */ + my_bool inactive; /* Connection inactive (has been shutdown) */ + char desc[VIO_DESCRIPTION_SIZE]; /* Description string. This member MUST NOT be used directly, but only via function @@ -226,7 +227,16 @@ struct st_vio char *read_end; /* end of unfetched data */ int read_timeout; /* Timeout value (ms) for read ops. */ int write_timeout; /* Timeout value (ms) for write ops. */ - /* function pointers. They are similar for socket/SSL/whatever */ + + /* + VIO vtable interface to be implemented by VIO's like SSL, Socket, + Named Pipe, etc. + */ + + /* + viodelete is responsible for cleaning up the VIO object by freeing + internal buffers, closing descriptors, handles. + */ void (*viodelete)(Vio*); int (*vioerrno)(Vio*); size_t (*read)(Vio*, uchar *, size_t); @@ -238,7 +248,12 @@ struct st_vio void (*in_addr)(Vio*, struct sockaddr_storage*); my_bool (*should_retry)(Vio*); my_bool (*was_timeout)(Vio*); - int (*vioclose)(Vio*); + /* + vioshutdown is resposnible to shutdown/close the channel, so that no + further communications can take place, however any related buffers, + descriptors, handles can remain valid after a shutdown. + */ + int (*vioshutdown)(Vio*); my_bool (*is_connected)(Vio*); my_bool (*has_data) (Vio*); int (*io_wait)(Vio*, enum enum_vio_io_event, int); @@ -248,7 +263,7 @@ struct st_vio HANDLE hPipe; #endif #ifdef HAVE_OPENSSL - void *ssl_arg; + void *ssl_arg; #endif #ifdef HAVE_SMEM HANDLE handle_file_map; === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2012-12-14 15:20:59 +0000 +++ b/sql/rpl_slave.cc 2013-01-02 08:09:22 +0000 @@ -3883,7 +3883,7 @@ static int try_to_reconnect(THD *thd, MY { mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT; thd->proc_info= messages[SLAVE_RECON_MSG_WAIT]; -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN thd->clear_active_vio(); #endif end_server(mysql); @@ -4291,11 +4291,11 @@ err: Here we need to clear the active VIO before closing the connection with the master. The reason is that THD::awake() might be called from terminate_slave_thread() because somebody - issued a STOP SLAVE. If that happends, the close_active_vio() + issued a STOP SLAVE. If that happends, the shutdown_active_vio() can be called in the middle of closing the VIO associated with the 'mysql' object, causing a crash. */ -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN thd->clear_active_vio(); #endif mysql_close(mysql); @@ -6576,7 +6576,7 @@ err: extern "C" void slave_io_thread_detach_vio() { -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN THD *thd= current_thd; if (thd && thd->slave_thread) thd->clear_active_vio(); @@ -6754,7 +6754,7 @@ replication resumed in log '%s' at posit general_log_print(thd, COM_CONNECT_OUT, "%s@%s:%d", mi->get_user(), mi->host, mi->port); } -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN thd->set_active_vio(mysql->net.vio); #endif } === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2012-12-19 09:35:15 +0000 +++ b/sql/sql_class.cc 2013-01-02 08:09:22 +0000 @@ -329,7 +329,7 @@ void thd_unlock_thread_count(THD *) void thd_close_connection(THD *thd) { if (thd->net.vio) - vio_close(thd->net.vio); + vio_shutdown(thd->net.vio); } /** @@ -988,7 +988,7 @@ THD::THD(bool enable_plugins) peer_port= 0; // For SHOW PROCESSLIST transaction.m_pending_rows_event= 0; transaction.flags.enabled= true; -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN active_vio = 0; #endif mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST); @@ -1711,7 +1711,7 @@ void THD::awake(THD::killed_state state_ if (state_to_set != THD::KILL_QUERY) { -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN if (this != current_thd) { /* @@ -1740,7 +1740,7 @@ void THD::awake(THD::killed_state state_ reading the next statement. */ - close_active_vio(); + shutdown_active_vio(); } #endif @@ -1809,20 +1809,20 @@ void THD::disconnect() killed= THD::KILL_CONNECTION; -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN /* Since a active vio might might have not been set yet, in any case save a reference to avoid closing a inexistent one or closing the vio twice if there is a active one. */ vio= active_vio; - close_active_vio(); + shutdown_active_vio(); #endif /* Disconnect even if a active vio is not associated. */ if (net.vio != vio && net.vio != NULL) { - vio_close(net.vio); + vio_shutdown(net.vio); } mysql_mutex_unlock(&LOCK_thd_data); @@ -2269,15 +2269,15 @@ int THD::send_explain_fields(select_resu Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)); } -#ifdef SIGNAL_WITH_VIO_CLOSE -void THD::close_active_vio() +#ifdef SIGNAL_WITH_VIO_SHUTDOWN +void THD::shutdown_active_vio() { - DBUG_ENTER("close_active_vio"); + DBUG_ENTER("shutdown_active_vio"); mysql_mutex_assert_owner(&LOCK_thd_data); #ifndef EMBEDDED_LIBRARY if (active_vio) { - vio_close(active_vio); + vio_shutdown(active_vio); active_vio = 0; } #endif === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2012-12-13 11:16:18 +0000 +++ b/sql/sql_class.h 2013-01-02 08:09:22 +0000 @@ -2389,7 +2389,7 @@ public: #ifndef __WIN__ sigset_t signals; #endif -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN Vio* active_vio; #endif /* @@ -3009,7 +3009,7 @@ public: void cleanup_after_query(); bool store_globals(); bool restore_globals(); -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN inline void set_active_vio(Vio* vio) { mysql_mutex_lock(&LOCK_thd_data); @@ -3022,7 +3022,7 @@ public: active_vio = 0; mysql_mutex_unlock(&LOCK_thd_data); } - void close_active_vio(); + void shutdown_active_vio(); #endif void awake(THD::killed_state state_to_set); === modified file 'sql/sql_connect.cc' --- a/sql/sql_connect.cc 2012-11-21 12:44:48 +0000 +++ b/sql/sql_connect.cc 2013-01-02 08:09:22 +0000 @@ -501,7 +501,7 @@ static int check_connection(THD *thd) DBUG_PRINT("info", ("New connection received on %s", vio_description(net->vio))); -#ifdef SIGNAL_WITH_VIO_CLOSE +#ifdef SIGNAL_WITH_VIO_SHUTDOWN thd->set_active_vio(net->vio); #endif === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2012-11-21 12:44:48 +0000 +++ b/sql/sql_prepare.cc 2013-01-02 08:09:22 +0000 @@ -2644,7 +2644,7 @@ void mysqld_stmt_execute(THD *thd, char sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size); /* Close connection socket; for use with client testing (Bug#43560). */ - DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio);); + DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_shutdown(thd->net.vio);); DBUG_VOID_RETURN; } === modified file 'vio/vio.c' --- a/vio/vio.c 2012-12-11 15:56:03 +0000 +++ b/vio/vio.c 2013-01-02 08:09:22 +0000 @@ -84,7 +84,7 @@ static void vio_init(Vio *vio, enum enum vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; vio->was_timeout =vio_was_timeout; - vio->vioclose =vio_close_pipe; + vio->vioshutdown =vio_shutdown_pipe; vio->peer_addr =vio_peer_addr; vio->io_wait =no_io_wait; vio->is_connected =vio_is_connected_pipe; @@ -95,7 +95,7 @@ static void vio_init(Vio *vio, enum enum #ifdef HAVE_SMEM if (type == VIO_TYPE_SHARED_MEMORY) { - vio->viodelete =vio_delete; + vio->viodelete =vio_delete_shared_memory; vio->vioerrno =vio_errno; vio->read =vio_read_shared_memory; vio->write =vio_write_shared_memory; @@ -103,7 +103,7 @@ static void vio_init(Vio *vio, enum enum vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; vio->was_timeout =vio_was_timeout; - vio->vioclose =vio_close_shared_memory; + vio->vioshutdown =vio_shutdown_shared_memory; vio->peer_addr =vio_peer_addr; vio->io_wait =no_io_wait; vio->is_connected =vio_is_connected_shared_memory; @@ -122,7 +122,7 @@ static void vio_init(Vio *vio, enum enum vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; vio->was_timeout =vio_was_timeout; - vio->vioclose =vio_ssl_close; + vio->vioshutdown =vio_ssl_shutdown; vio->peer_addr =vio_peer_addr; vio->io_wait =vio_io_wait; vio->is_connected =vio_is_connected; @@ -139,7 +139,7 @@ static void vio_init(Vio *vio, enum enum vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; vio->was_timeout =vio_was_timeout; - vio->vioclose =vio_close; + vio->vioshutdown =vio_shutdown; vio->peer_addr =vio_peer_addr; vio->io_wait =vio_io_wait; vio->is_connected =vio_is_connected; @@ -335,8 +335,8 @@ void vio_delete(Vio* vio) if (!vio) return; /* It must be safe to delete null pointers. */ - if (vio->type != VIO_CLOSED) - vio->vioclose(vio); + if (vio->inactive == FALSE) + vio->vioshutdown(vio); my_free(vio->read_buffer); my_free(vio); } === modified file 'vio/vio_priv.h' --- a/vio/vio_priv.h 2011-09-07 10:08:09 +0000 +++ b/vio/vio_priv.h 2013-01-02 07:54:14 +0000 @@ -29,14 +29,15 @@ size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size); size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size); my_bool vio_is_connected_pipe(Vio *vio); -int vio_close_pipe(Vio * vio); +int vio_shutdown_pipe(Vio * vio); #endif #ifdef HAVE_SMEM size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size); size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size); my_bool vio_is_connected_shared_memory(Vio *vio); -int vio_close_shared_memory(Vio * vio); +int vio_shutdown_shared_memory(Vio * vio); +void vio_delete_shared_memory(Vio *vio); #endif my_bool vio_buff_has_data(Vio *vio); @@ -50,7 +51,7 @@ size_t vio_ssl_read(Vio *vio,uchar* buf, size_t vio_ssl_write(Vio *vio,const uchar* buf, size_t size); /* When the workday is over... */ -int vio_ssl_close(Vio *vio); +int vio_ssl_shutdown(Vio *vio); void vio_ssl_delete(Vio *vio); my_bool vio_ssl_has_data(Vio *vio); === modified file 'vio/viopipe.c' --- a/vio/viopipe.c 2011-06-06 19:57:05 +0000 +++ b/vio/viopipe.c 2013-01-02 07:54:14 +0000 @@ -101,17 +101,17 @@ my_bool vio_is_connected_pipe(Vio *vio) } -int vio_close_pipe(Vio *vio) +int vio_shutdown_pipe(Vio *vio) { BOOL ret; - DBUG_ENTER("vio_close_pipe"); + DBUG_ENTER("vio_shutdown_pipe"); CancelIo(vio->hPipe); CloseHandle(vio->overlapped.hEvent); DisconnectNamedPipe(vio->hPipe); ret= CloseHandle(vio->hPipe); - vio->type= VIO_CLOSED; + vio->inactive= TRUE; vio->hPipe= NULL; vio->mysql_socket= MYSQL_INVALID_SOCKET; === modified file 'vio/vioshm.c' --- a/vio/vioshm.c 2011-06-06 19:57:05 +0000 +++ b/vio/vioshm.c 2013-01-02 07:54:14 +0000 @@ -43,7 +43,7 @@ size_t vio_read_shared_memory(Vio *vio, FALSE, timeout); /* - WaitForMultipleObjects can return next values: + WaitForMultipleObjects can return next values: WAIT_OBJECT_0+0 - event from vio->event_server_wrote WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything @@ -153,64 +153,73 @@ my_bool vio_is_connected_shared_memory(V } -/** - Close shared memory and DBUG_PRINT any errors that happen on closing. - @return Zero if all closing functions succeed, and nonzero otherwise. +void vio_delete_shared_memory(Vio *vio) +{ + DBUG_ENTER("vio_delete_shared_memory"); + + if (!vio) + DBUG_VOID_RETURN; + + if (vio->inactive == FALSE) + vio->vioshutdown(vio); + + /* + Close all handlers. UnmapViewOfFile and CloseHandle return non-zero + result if they are success. + */ + if (UnmapViewOfFile(vio->handle_map) == 0) + DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); + + if (CloseHandle(vio->event_server_wrote) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); + + if (CloseHandle(vio->event_server_read) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); + + if (CloseHandle(vio->event_client_wrote) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); + + if (CloseHandle(vio->event_client_read) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); + + if (CloseHandle(vio->handle_file_map) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); + + if (CloseHandle(vio->event_conn_closed) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); + + vio_delete(vio); + + DBUG_VOID_RETURN; +} + +/* + When "kill connection xx" is executed on an arbitrary thread it calls + THD::shutdown_active_vio() on the THD referred to by xx. Since the + thread serving the connection xx might be in the middle of a vio_read + or vio_write, we cannot unmap the shared memory here. + + Therefore we here just signal the connection_closed event and give + the thread servicing connection xx a chance to gracefully exit. + All handles are closed and the VIO is cleaned up when vio_delete() is + called and this completes the vio cleanup operation in its entirety. */ -int vio_close_shared_memory(Vio * vio) +int vio_shutdown_shared_memory(Vio * vio) { - int error_count= 0; - DBUG_ENTER("vio_close_shared_memory"); - if (vio->type != VIO_CLOSED) + DBUG_ENTER("vio_shutdown_shared_memory"); + if (vio->inactive == FALSE) { /* Set event_conn_closed for notification of both client and server that connection is closed */ SetEvent(vio->event_conn_closed); - /* - Close all handlers. UnmapViewOfFile and CloseHandle return non-zero - result if they are success. - */ - if (UnmapViewOfFile(vio->handle_map) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); - } - if (CloseHandle(vio->event_server_wrote) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); - } - if (CloseHandle(vio->event_server_read) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); - } - if (CloseHandle(vio->event_client_wrote) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); - } - if (CloseHandle(vio->event_client_read) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); - } - if (CloseHandle(vio->handle_file_map) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); - } - if (CloseHandle(vio->event_conn_closed) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); - } } - vio->type= VIO_CLOSED; + + vio->inactive= TRUE; vio->mysql_socket= MYSQL_INVALID_SOCKET; - DBUG_RETURN(error_count); + + DBUG_RETURN(0); } #endif /* #if defined(_WIN32) && defined(HAVE_SMEM) */ === modified file 'vio/viosocket.c' --- a/vio/viosocket.c 2012-11-09 12:19:42 +0000 +++ b/vio/viosocket.c 2013-01-02 08:09:22 +0000 @@ -400,12 +400,12 @@ vio_was_timeout(Vio *vio) } -int vio_close(Vio * vio) +int vio_shutdown(Vio * vio) { int r=0; - DBUG_ENTER("vio_close"); + DBUG_ENTER("vio_shutdown"); - if (vio->type != VIO_CLOSED) + if (vio->inactive == FALSE) { DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET || @@ -422,7 +422,7 @@ int vio_close(Vio * vio) DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); /* FIXME: error handling (not critical for MySQL) */ } - vio->type= VIO_CLOSED; + vio->inactive= TRUE; vio->mysql_socket= MYSQL_INVALID_SOCKET; DBUG_RETURN(r); } === modified file 'vio/viossl.c' --- a/vio/viossl.c 2011-09-07 10:08:09 +0000 +++ b/vio/viossl.c 2013-01-02 07:54:14 +0000 @@ -210,11 +210,11 @@ static long yassl_send(void *ptr, const #endif -int vio_ssl_close(Vio *vio) +int vio_ssl_shutdown(Vio *vio) { int r= 0; SSL *ssl= (SSL*)vio->ssl_arg; - DBUG_ENTER("vio_ssl_close"); + DBUG_ENTER("vio_ssl_shutdown"); if (ssl) { @@ -245,7 +245,7 @@ int vio_ssl_close(Vio *vio) break; } } - DBUG_RETURN(vio_close(vio)); + DBUG_RETURN(vio_shutdown(vio)); } @@ -254,8 +254,8 @@ void vio_ssl_delete(Vio *vio) if (!vio) return; /* It must be safe to delete null pointer */ - if (vio->type == VIO_TYPE_SSL) - vio_ssl_close(vio); /* Still open, close connection first */ + if (vio->inactive == FALSE) + vio_ssl_shutdown(vio); /* Still open, close connection first */ if (vio->ssl_arg) { No bundle (reason: useless for push emails).