Commit 6cc6ec2f authored by Ondřej Kuzník's avatar Ondřej Kuzník
Browse files

ITS#9600 Do not hold locks while calling into back-monitor

parent 8968d131
......@@ -600,22 +600,29 @@ client_init(
}
c->c_write_event = event;
CONNECTION_LOCK(c);
#ifdef BALANCER_MODULE
if ( lload_monitor_client_subsys ) {
acquire_ref( &c->c_refcnt );
CONNECTION_UNLOCK(c);
if ( lload_monitor_conn_entry_create(
c, lload_monitor_client_subsys ) ) {
CONNECTION_LOCK(c);
RELEASE_REF( c, c_refcnt, c->c_destroy );
goto fail;
}
CONNECTION_LOCK(c);
RELEASE_REF( c, c_refcnt, c->c_destroy );
}
#endif /* BALANCER_MODULE */
c->c_destroy = client_destroy;
c->c_unlink = client_unlink;
c->c_pdu_cb = handle_one_request;
CONNECTION_LOCK(c);
/* We only register the write event when we have data pending */
event_add( c->c_read_event, c->c_read_timeout );
#ifdef BALANCER_MODULE
if ( lload_monitor_client_subsys &&
lload_monitor_conn_entry_create(
c, lload_monitor_client_subsys ) ) {
goto fail;
}
#endif /* BALANCER_MODULE */
checked_lock( &clients_mutex );
LDAP_CIRCLEQ_INSERT_TAIL( &clients, c, c_next );
checked_unlock( &clients_mutex );
......@@ -623,6 +630,14 @@ client_init(
return c;
fail:
if ( !IS_ALIVE( c, c_live ) ) {
/*
* Released while we were unlocked, it's scheduled for destruction
* already
*/
return NULL;
}
if ( c->c_write_event ) {
event_free( c->c_write_event );
c->c_write_event = NULL;
......
......@@ -522,7 +522,7 @@ lload_connection_close( LloadConnection *c, void *arg )
"marking connection connid=%lu closing\n",
c->c_connid );
/* We were approached from the connection list */
/* We were approached from the connection list or cn=monitor */
assert( IS_ALIVE( c, c_refcnt ) );
/* Need to acquire this first, even if we won't need it */
......
......@@ -963,15 +963,26 @@ upstream_init( ber_socket_t s, LloadBackend *b )
/* We only add the write event when we have data pending */
c->c_write_event = event;
c->c_destroy = upstream_destroy;
c->c_unlink = upstream_unlink;
#ifdef BALANCER_MODULE
if ( b->b_monitor && lload_monitor_conn_entry_create( c, b->b_monitor ) ) {
goto fail;
if ( b->b_monitor ) {
acquire_ref( &c->c_refcnt );
CONNECTION_UNLOCK(c);
checked_unlock( &b->b_mutex );
if ( lload_monitor_conn_entry_create( c, b->b_monitor ) ) {
RELEASE_REF( c, c_refcnt, c->c_destroy );
checked_lock( &b->b_mutex );
CONNECTION_LOCK(c);
goto fail;
}
checked_lock( &b->b_mutex );
CONNECTION_LOCK(c);
RELEASE_REF( c, c_refcnt, c->c_destroy );
}
#endif /* BALANCER_MODULE */
c->c_destroy = upstream_destroy;
c->c_unlink = upstream_unlink;
#ifdef HAVE_TLS
if ( c->c_is_tls == LLOAD_CLEARTEXT ) {
#endif /* HAVE_TLS */
......@@ -1015,6 +1026,14 @@ upstream_init( ber_socket_t s, LloadBackend *b )
return c;
fail:
if ( !IS_ALIVE( c, c_live ) ) {
/*
* Released while we were unlocked, it's scheduled for destruction
* already
*/
return NULL;
}
if ( c->c_write_event ) {
event_del( c->c_write_event );
event_free( c->c_write_event );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment