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:
vraatikka
2013-08-22 10:42:18 +03:00
parent 4138281183
commit 0401290021
4 changed files with 56 additions and 15 deletions

View File

@ -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)
{ {
service->router->closeSession( void* rsession = NULL;
service->router_instance, /**
dcb->session->router_session); * 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_instance,
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);
} }

View File

@ -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));

View File

@ -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 */

View File

@ -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);
/* close the active session */ if (rsession != NULL) {
router->closeSession(router_instance, rsession); /* close the active session */
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;