diff --git a/include/ma_pvio.h b/include/ma_pvio.h index d76cd8ea..d98fa6c4 100644 --- a/include/ma_pvio.h +++ b/include/ma_pvio.h @@ -105,6 +105,7 @@ struct st_ma_pvio_methods my_bool (*is_blocking)(MARIADB_PVIO *pvio); my_bool (*is_alive)(MARIADB_PVIO *pvio); my_bool (*has_data)(MARIADB_PVIO *pvio, ssize_t *data_len); + int(*shutdown)(MARIADB_PVIO *pvio); }; /* Function prototypes */ diff --git a/include/mysql.h b/include/mysql.h index 5a48bc41..964587a8 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -570,6 +570,7 @@ my_socket STDCALL mysql_get_socket(MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); my_bool STDCALL mariadb_reconnect(MYSQL *mysql); +int STDCALL mariadb_cancel(MYSQL *mysql); /* Async API */ int STDCALL mysql_close_start(MYSQL *sock); diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 5a100ef7..464710d0 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -3804,6 +3804,24 @@ my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *a return mariadb_get_infov(mysql, value, arg); } +/* + Immediately aborts connection, making all subsequent read/write operations fail. + Does not invalidate memory used for mysql structure, nor closes any communication + channels - mysql_close is still needed. + Useful to break long query, in situation sending KILL is not possible. +*/ +int STDCALL mariadb_cancel(MYSQL *mysql) +{ + if (!mysql || !mysql->net.pvio || !mysql->net.pvio->methods || !mysql->net.pvio->methods->shutdown) + { + return 1; + } + else + { + MARIADB_PVIO *pvio = mysql->net.pvio; + return pvio->methods->shutdown(pvio); + } +} #undef STDCALL /* API functions for usage in dynamic plugins */ struct st_mariadb_api MARIADB_API= diff --git a/plugins/pvio/pvio_npipe.c b/plugins/pvio/pvio_npipe.c index 61367b4b..3d081cf9 100644 --- a/plugins/pvio/pvio_npipe.c +++ b/plugins/pvio/pvio_npipe.c @@ -45,6 +45,7 @@ int pvio_npipe_fast_send(MARIADB_PVIO *pvio); int pvio_npipe_keepalive(MARIADB_PVIO *pvio); my_bool pvio_npipe_get_handle(MARIADB_PVIO *pvio, void *handle); my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio); +int pvio_npipe_shutdown(MARIADB_PVIO *pvio); struct st_ma_pvio_methods pvio_npipe_methods= { pvio_npipe_set_timeout, @@ -60,7 +61,8 @@ struct st_ma_pvio_methods pvio_npipe_methods= { pvio_npipe_fast_send, pvio_npipe_keepalive, pvio_npipe_get_handle, - pvio_npipe_is_blocking + pvio_npipe_is_blocking, + pvio_npipe_shutdown }; #ifndef HAVE_NPIPE_DYNAMIC @@ -354,4 +356,13 @@ my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio) return (flags & PIPE_NOWAIT) ? 0 : 1; } +int pvio_npipe_shutdown(MARIADB_PVIO *pvio) +{ + HANDLE h; + if (pvio_npipe_get_handle(pvio, &h) == 0) + { + return(CancelIoEx(h, NULL) ? 0 : 1); + } + return 1; +} #endif diff --git a/plugins/pvio/pvio_shmem.c b/plugins/pvio/pvio_shmem.c index fc4f928d..f27943ad 100644 --- a/plugins/pvio/pvio_shmem.c +++ b/plugins/pvio/pvio_shmem.c @@ -40,7 +40,7 @@ int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout my_bool pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value); my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo); my_bool pvio_shm_close(MARIADB_PVIO *pvio); - +int pvio_shm_shutdown(MARIADB_PVIO *pvio); struct st_ma_pvio_methods pvio_shm_methods= { pvio_shm_set_timeout, @@ -57,7 +57,9 @@ struct st_ma_pvio_methods pvio_shm_methods= { NULL, NULL, NULL, - NULL + NULL, + NULL, + pvio_shm_shutdown }; #ifndef HAVE_SHMEM_DYNAMIC @@ -438,5 +440,11 @@ my_bool pvio_shm_is_blocking(MARIADB_PVIO *pvio) return 1; } +int pvio_shm_shutdown(MARIADB_PVIO *pvio) +{ + PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data; + if (pvio_shm) + return (SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]) ? 0 : 1); +} #endif diff --git a/plugins/pvio/pvio_socket.c b/plugins/pvio/pvio_socket.c index 96e5750c..1488e47b 100644 --- a/plugins/pvio/pvio_socket.c +++ b/plugins/pvio/pvio_socket.c @@ -76,6 +76,7 @@ my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle); my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio); my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio); my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len); +int pvio_socket_shutdown(MARIADB_PVIO *pvio); static int pvio_socket_init(char *unused1, size_t unused2, @@ -99,7 +100,8 @@ struct st_ma_pvio_methods pvio_socket_methods= { pvio_socket_get_handle, pvio_socket_is_blocking, pvio_socket_is_alive, - pvio_socket_has_data + pvio_socket_has_data, + pvio_socket_shutdown }; #ifndef HAVE_SOCKET_DYNAMIC @@ -1023,3 +1025,19 @@ my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) return 0; } /* }}} */ + +int pvio_socket_shutdown(MARIADB_PVIO *pvio) +{ + int rc = 0; + if (pvio && pvio->data) + { + my_socket s = ((struct st_pvio_socket *)pvio->data)->socket; +#ifdef _WIN32 + rc = shutdown(s, SD_BOTH); + CancelIoEx((HANDLE)s, NULL); +#else + rc = shutdown(s, SHUT_RDWR); +#endif + } + return -1; +}