Added spinlock ses_lock to struct SESSION to ensure that for each session closeSession is called only once.
closeSession is called from mysql_backend.c:gw_read_backend_event, and from dcb.c:dcb_close. This is part of Bug #163.
This commit is contained in:
@ -611,11 +611,29 @@ dcb_close(DCB *dcb)
|
|||||||
*/
|
*/
|
||||||
SERVICE *service = dcb->session->service;
|
SERVICE *service = dcb->session->service;
|
||||||
|
|
||||||
if (service && service->router && dcb->session->router_session)
|
if (service != NULL &&
|
||||||
|
service->router != NULL &&
|
||||||
|
dcb->session->router_session != NULL)
|
||||||
{
|
{
|
||||||
|
void* rsession = NULL;
|
||||||
|
/**
|
||||||
|
* Protect call of closeSession.
|
||||||
|
*/
|
||||||
|
spinlock_acquire(&dcb->session->ses_lock);
|
||||||
|
rsession = dcb->session->router_session;
|
||||||
|
dcb->session->router_session = NULL;
|
||||||
|
spinlock_release(&dcb->session->ses_lock);
|
||||||
|
|
||||||
|
if (rsession != NULL) {
|
||||||
service->router->closeSession(
|
service->router->closeSession(
|
||||||
service->router_instance,
|
service->router_instance,
|
||||||
dcb->session->router_session);
|
rsession);
|
||||||
|
} else {
|
||||||
|
skygw_log_write_flush(
|
||||||
|
LOGFILE_TRACE,
|
||||||
|
"%lu [dcb_close] rsession was NULL in dcb_close.",
|
||||||
|
pthread_self());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
session_free(dcb->session);
|
session_free(dcb->session);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,7 @@ SESSION *session;
|
|||||||
|
|
||||||
if ((session = (SESSION *)malloc(sizeof(SESSION))) == NULL)
|
if ((session = (SESSION *)malloc(sizeof(SESSION))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
spinlock_init(&session->ses_lock);
|
||||||
session->service = service;
|
session->service = service;
|
||||||
session->client = client;
|
session->client = client;
|
||||||
memset(&session->stats, 0, sizeof(SESSION_STATS));
|
memset(&session->stats, 0, sizeof(SESSION_STATS));
|
||||||
|
|||||||
@ -33,6 +33,8 @@
|
|||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
struct dcb;
|
struct dcb;
|
||||||
struct service;
|
struct service;
|
||||||
@ -52,6 +54,7 @@ typedef struct {
|
|||||||
* and originating service together for the client session.
|
* and originating service together for the client session.
|
||||||
*/
|
*/
|
||||||
typedef struct session {
|
typedef struct session {
|
||||||
|
SPINLOCK ses_lock;
|
||||||
int state; /**< Current descriptor state */
|
int state; /**< Current descriptor state */
|
||||||
struct dcb *client; /**< The client connection */
|
struct dcb *client; /**< The client connection */
|
||||||
struct dcb *backends; /**< The set of backend servers */
|
struct dcb *backends; /**< The set of backend servers */
|
||||||
|
|||||||
@ -163,13 +163,20 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
rsession = session->router_session;
|
rsession = session->router_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read backed auth reply */
|
/* read backed auth reply */
|
||||||
rv = gw_receive_backend_auth(backend_protocol);
|
rv = gw_receive_backend_auth(backend_protocol);
|
||||||
|
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
case MYSQL_FAILED_AUTHENTICATION:
|
case MYSQL_FAILED_AUTHENTICATION:
|
||||||
fprintf(stderr, ">>>> Backend Auth failed for user [%s], fd %i\n", current_session->user, dcb->fd);
|
skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [gw_read_backend_event] caught "
|
||||||
|
"MYSQL_FAILED_AUTHENTICATION from "
|
||||||
|
"gw_receive_backend_auth. Fd %d, user %s. "
|
||||||
|
"Closing the session.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb->fd,
|
||||||
|
current_session->user);
|
||||||
|
|
||||||
backend_protocol->state = MYSQL_AUTH_FAILED;
|
backend_protocol->state = MYSQL_AUTH_FAILED;
|
||||||
|
|
||||||
@ -179,18 +186,30 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
"Connection to backend lost right now");
|
"Connection to backend lost right now");
|
||||||
|
/**
|
||||||
|
* Protect call of closeSession.
|
||||||
|
*/
|
||||||
|
spinlock_acquire(&session->ses_lock);
|
||||||
|
rsession = session->router_session;
|
||||||
|
session->router_session = NULL;
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
|
||||||
|
if (rsession != NULL) {
|
||||||
/* close the active session */
|
/* close the active session */
|
||||||
router->closeSession(router_instance, rsession);
|
router->closeSession(router_instance, rsession);
|
||||||
|
}
|
||||||
/* force the router_session to NULL
|
|
||||||
* Later we will implement a proper status for the session
|
|
||||||
*/
|
|
||||||
session->router_session = NULL;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case MYSQL_SUCCESFUL_AUTHENTICATION:
|
case MYSQL_SUCCESFUL_AUTHENTICATION:
|
||||||
|
skygw_log_write_flush(
|
||||||
|
LOGFILE_TRACE,
|
||||||
|
"%lu [gw_read_backend_event] caught "
|
||||||
|
"MYSQL_SUCCESFUL_AUTHENTICATION from "
|
||||||
|
"gw_receive_backend_auth. Fd %d, user %s.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb->fd,
|
||||||
|
current_session->user);
|
||||||
|
|
||||||
spinlock_acquire(&dcb->authlock);
|
spinlock_acquire(&dcb->authlock);
|
||||||
|
|
||||||
backend_protocol->state = MYSQL_IDLE;
|
backend_protocol->state = MYSQL_IDLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user