2012-04-13 12:47:30 +00:00
/*
2015-02-24 18:19:20 +00:00
* SSLsplit - transparent SSL / TLS interception
2016-03-25 11:19:23 +00:00
* Copyright ( c ) 2009 - 2016 , Daniel Roethlisberger < daniel @ roe . ch >
2012-04-13 12:47:30 +00:00
* All rights reserved .
* http : //www.roe.ch/SSLsplit
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
2015-02-24 18:19:20 +00:00
* notice , this list of conditions , and the following disclaimer .
2012-04-13 12:47:30 +00:00
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "pxythrmgr.h"
# include "sys.h"
# include "log.h"
2017-06-29 21:38:37 +00:00
# include "pxyconn.h"
2012-04-13 12:47:30 +00:00
2014-06-21 17:20:34 +00:00
# include <string.h>
2017-07-02 14:47:26 +00:00
# include <event2/bufferevent.h>
2012-04-13 12:47:30 +00:00
# include <pthread.h>
2017-06-30 21:29:39 +00:00
# include <assert.h>
2012-04-13 12:47:30 +00:00
/*
* Proxy thread manager : manages the connection handling worker threads
* and the per - thread resources ( i . e . event bases ) . The load is shared
* across num_cpu * 2 connection handling threads , using the number of
* currently assigned connections as the sole metric .
*
* The attach and detach functions are thread - safe .
*/
2017-07-03 23:12:17 +00:00
# define THR_TIMER_TIMEOUT 10
# define THR_TIMER_PRINT_INFO_TIMEOUT 1*THR_TIMER_TIMEOUT
2017-07-14 19:34:15 +00:00
# define CONN_EXPIRE_TIME 120
static void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_get_thr_expired_conns ( pxy_thr_ctx_t * tctx , pxy_conn_ctx_t * * expired_conns )
2017-07-14 19:34:15 +00:00
{
* expired_conns = NULL ;
time_t now = time ( NULL ) ;
2017-07-15 01:07:42 +00:00
pxy_conn_ctx_t * ctx = tctx - > conns ;
while ( ctx ) {
unsigned long elapsed_time = now - ctx - > access_time ;
2017-07-14 19:34:15 +00:00
if ( elapsed_time > CONN_EXPIRE_TIME ) {
2017-07-15 01:07:42 +00:00
ctx - > next_expired = * expired_conns ;
* expired_conns = ctx ;
2017-07-14 19:34:15 +00:00
}
2017-07-15 01:07:42 +00:00
ctx = ctx - > next ;
2017-07-14 19:34:15 +00:00
}
2017-07-15 01:07:42 +00:00
ctx = * expired_conns ;
if ( ctx ) {
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_get_thr_expired_conns: ----------------------------- Expired conns: thr=%d \n " , tctx - > thridx ) ;
while ( ctx ) {
pxy_conn_ctx_t * next = ctx - > next_expired ;
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_get_expired_conns: thr=%d, fd=%d, child_fd=%d, time=%lld \n " ,
2017-07-15 01:07:42 +00:00
ctx - > thr - > thridx , ctx - > fd , ctx - > child_fd , ( long int ) now - ctx - > access_time ) ;
ctx = next ;
2017-07-14 19:34:15 +00:00
}
}
}
static void
pxy_thrmgr_print_child ( pxy_conn_child_ctx_t * child_ctx , int count )
{
assert ( child_ctx ! = NULL ) ;
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> .......... pxy_thrmgr_print_child: thr=%d, cont=%d, src=%d, dst=%d, c=%d-%d, ci=%d \n " ,
2017-07-15 01:07:42 +00:00
child_ctx - > parent - > thr - > thridx , count , child_ctx - > src_fd , child_ctx - > dst_fd , child_ctx - > src . closed , child_ctx - > dst . closed , child_ctx - > idx ) ;
2017-07-14 19:34:15 +00:00
if ( child_ctx - > next ) {
pxy_thrmgr_print_child ( child_ctx - > next , count ) ;
}
}
static void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_print_thr_info ( pxy_thr_ctx_t * tctx )
2017-07-14 19:34:15 +00:00
{
2017-07-15 01:07:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_print_thr_info: thr=%d, load=%lu \n " , tctx - > thridx , tctx - > load ) ;
2017-07-14 19:34:15 +00:00
2017-07-15 01:07:42 +00:00
if ( tctx - > conns ) {
2017-07-14 19:34:15 +00:00
time_t now = time ( NULL ) ;
2017-07-15 01:07:42 +00:00
pxy_conn_ctx_t * ctx = tctx - > conns ;
2017-07-14 19:34:15 +00:00
int count = 0 ;
2017-07-15 01:07:42 +00:00
while ( ctx ) {
2017-07-14 19:34:15 +00:00
char * host , * port ;
2017-07-15 01:07:42 +00:00
if ( ctx - > addrlen = = 0 | | ( sys_sockaddr_str ( ( struct sockaddr * ) & ctx - > addr , ctx - > addrlen , & host , & port ) ! = 0 ) ) {
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_print_thr_info: Cannot get host:port: thr=%d, cont=%d, fd=%d, child_fd=%d \n " , tctx - > thridx , count , ctx - > fd , ctx - > child_fd ) ;
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_print_thr_info: thr=%d, cont=%d, fd=%d, child_fd=%d, src=%d, dst=%d, srv_dst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, pe=%d ce=%d tcc=%d, time=%lld \n " ,
2017-07-15 01:07:42 +00:00
tctx - > thridx , count , ctx - > fd , ctx - > child_fd , ctx - > src_fd , ctx - > dst_fd , ctx - > srv_dst_fd , ctx - > child_src_fd , ctx - > child_dst_fd ,
ctx - > src_closed , ctx - > dst_closed , ctx - > srv_dst_closed , ctx - > child_src_closed , ctx - > child_dst_closed , ctx ? 1 : 0 , ctx - > children ? 1 : 0 , ctx - > child_count , ( long int ) now - ctx - > access_time ) ;
2017-07-14 19:34:15 +00:00
} else {
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>> pxy_thrmgr_print_thr_info: thr=%d, cont=%d, fd=%d, child_fd=%d, src=%d, dst=%d, srv_dst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, pe=%d ce=%d tcc=%d, time=%lld, addr=%s:%s \n " ,
2017-07-15 01:07:42 +00:00
tctx - > thridx , count , ctx - > fd , ctx - > child_fd , ctx - > src_fd , ctx - > dst_fd , ctx - > srv_dst_fd , ctx - > child_src_fd , ctx - > child_dst_fd ,
ctx - > src_closed , ctx - > dst_closed , ctx - > srv_dst_closed , ctx - > child_src_closed , ctx - > child_dst_closed , ctx ? 1 : 0 , ctx - > children ? 1 : 0 , ctx - > child_count , ( long int ) now - ctx - > access_time , host ? host : " ? " , port ? port : " ? " ) ;
2017-07-14 19:34:15 +00:00
free ( host ) ;
free ( port ) ;
}
2017-07-15 01:07:42 +00:00
if ( ctx - > children ) {
pxy_thrmgr_print_child ( ctx - > children , count ) ;
2017-07-14 19:34:15 +00:00
}
count + + ;
2017-07-15 01:07:42 +00:00
ctx = ctx - > next ;
2017-07-14 19:34:15 +00:00
}
}
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " >>> pxy_thrmgr_print_thr_info: EXIT \n " ) ;
}
2017-07-03 23:12:17 +00:00
2012-04-13 12:47:30 +00:00
/*
2017-07-14 19:34:15 +00:00
* Recurring timer event to prevent the event loops from exiting when
2012-04-13 12:47:30 +00:00
* they run out of events .
*/
static void
pxy_thrmgr_timer_cb ( UNUSED evutil_socket_t fd , UNUSED short what ,
UNUSED void * arg )
{
2017-07-03 23:12:17 +00:00
pxy_thr_ctx_t * ctx = arg ;
2017-07-14 19:34:15 +00:00
if ( ctx - > timer_cb_running ) {
return ;
}
ctx - > timer_cb_running = 1 ;
2017-07-12 19:37:36 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! pxy_thrmgr_timer_cb <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< THREAD TIMER thr=%d, load=%lu, to=%u \n " , ctx - > thridx , ctx - > load , ctx - > timeout_count ) ;
2017-07-15 01:07:42 +00:00
pxy_conn_ctx_t * expired = NULL ;
2017-07-03 23:12:17 +00:00
pxy_thrmgr_get_thr_expired_conns ( ctx , & expired ) ;
if ( expired ) {
time_t now = time ( NULL ) ;
while ( expired ) {
2017-07-15 01:07:42 +00:00
pxy_conn_ctx_t * next = expired - > next_expired ;
2017-07-03 23:12:17 +00:00
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " >>>>> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! pxy_thrmgr_timer_cb: DELETE thr=%d, fd=%d, child_fd=%d, time=%lld <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TIMED OUT \n " ,
2017-07-12 13:46:51 +00:00
expired - > thr - > thridx , expired - > fd , expired - > child_fd , ( long int ) now - expired - > access_time ) ;
2017-07-15 01:07:42 +00:00
pxy_conn_free ( expired ) ;
2017-07-03 23:12:17 +00:00
expired = next ;
}
}
ctx - > timeout_count + + ;
if ( ctx - > timeout_count * THR_TIMER_TIMEOUT > THR_TIMER_PRINT_INFO_TIMEOUT ) {
ctx - > timeout_count = 0 ;
pxy_thrmgr_print_thr_info ( ctx ) ;
}
2017-07-14 19:34:15 +00:00
ctx - > timer_cb_running = 0 ;
2012-04-13 12:47:30 +00:00
}
/*
* Thread entry point ; runs the event loop of the event base .
* Does not exit until the libevent loop is broken explicitly .
*/
static void *
pxy_thrmgr_thr ( void * arg )
{
pxy_thr_ctx_t * ctx = arg ;
2017-07-03 23:12:17 +00:00
struct timeval timer_delay = { THR_TIMER_TIMEOUT , 0 } ;
2012-04-13 12:47:30 +00:00
struct event * ev ;
2017-07-03 23:12:17 +00:00
ev = event_new ( ctx - > evbase , - 1 , EV_PERSIST , pxy_thrmgr_timer_cb , ctx ) ;
2012-04-13 12:47:30 +00:00
if ( ! ev )
return NULL ;
evtimer_add ( ev , & timer_delay ) ;
2012-10-23 20:52:54 +00:00
ctx - > running = 1 ;
2012-04-13 12:47:30 +00:00
event_base_dispatch ( ctx - > evbase ) ;
event_free ( ev ) ;
return NULL ;
}
2017-07-01 20:17:45 +00:00
/*
* Create new thread manager but do not start any threads yet .
* This gets called before forking to background .
*/
pxy_thrmgr_ctx_t *
pxy_thrmgr_new ( opts_t * opts )
{
pxy_thrmgr_ctx_t * ctx ;
if ( ! ( ctx = malloc ( sizeof ( pxy_thrmgr_ctx_t ) ) ) )
return NULL ;
memset ( ctx , 0 , sizeof ( pxy_thrmgr_ctx_t ) ) ;
ctx - > opts = opts ;
ctx - > num_thr = 2 * sys_get_cpu_cores ( ) ;
return ctx ;
}
/*
* Start the thread manager and associated threads .
* This must be called after forking .
*
* Returns - 1 on failure , 0 on success .
*/
2013-07-02 13:54:46 +00:00
int
2017-07-01 20:17:45 +00:00
pxy_thrmgr_run ( pxy_thrmgr_ctx_t * ctx )
2013-07-02 13:54:46 +00:00
{
2015-09-27 14:39:24 +00:00
int idx = - 1 , dns = 0 ;
2013-07-02 13:54:46 +00:00
2015-09-27 14:39:24 +00:00
dns = opts_has_dns_spec ( ctx - > opts ) ;
2017-07-01 20:17:45 +00:00
pthread_mutex_init ( & ctx - > mutex , NULL ) ;
2012-10-23 20:52:54 +00:00
2014-11-04 17:35:00 +00:00
if ( ! ( ctx - > thr = malloc ( ctx - > num_thr * sizeof ( pxy_thr_ctx_t * ) ) ) ) {
2014-01-15 00:03:12 +00:00
log_dbg_printf ( " Failed to allocate memory \n " ) ;
2012-04-13 12:47:30 +00:00
goto leave ;
2014-01-15 00:03:12 +00:00
}
2014-11-04 17:36:08 +00:00
memset ( ctx - > thr , 0 , ctx - > num_thr * sizeof ( pxy_thr_ctx_t * ) ) ;
2012-04-13 12:47:30 +00:00
for ( idx = 0 ; idx < ctx - > num_thr ; idx + + ) {
2014-01-15 00:03:12 +00:00
if ( ! ( ctx - > thr [ idx ] = malloc ( sizeof ( pxy_thr_ctx_t ) ) ) ) {
log_dbg_printf ( " Failed to allocate memory \n " ) ;
2012-04-13 12:47:30 +00:00
goto leave ;
2014-01-15 00:03:12 +00:00
}
2014-11-04 17:36:08 +00:00
memset ( ctx - > thr [ idx ] , 0 , sizeof ( pxy_thr_ctx_t ) ) ;
2012-04-13 12:47:30 +00:00
ctx - > thr [ idx ] - > evbase = event_base_new ( ) ;
2014-01-15 00:03:12 +00:00
if ( ! ctx - > thr [ idx ] - > evbase ) {
log_dbg_printf ( " Failed to create evbase %d \n " , idx ) ;
2012-04-13 12:47:30 +00:00
goto leave ;
2014-01-15 00:03:12 +00:00
}
2015-09-27 14:39:24 +00:00
if ( dns ) {
/* only create dns base if we actually need it later */
ctx - > thr [ idx ] - > dnsbase = evdns_base_new (
ctx - > thr [ idx ] - > evbase , 1 ) ;
if ( ! ctx - > thr [ idx ] - > dnsbase ) {
log_dbg_printf ( " Failed to create dnsbase %d \n " ,
idx ) ;
goto leave ;
}
2014-01-15 00:03:12 +00:00
}
2012-04-13 12:47:30 +00:00
ctx - > thr [ idx ] - > load = 0 ;
2012-10-23 20:52:54 +00:00
ctx - > thr [ idx ] - > running = 0 ;
2017-07-15 01:07:42 +00:00
ctx - > thr [ idx ] - > conns = NULL ;
2017-07-03 23:12:17 +00:00
ctx - > thr [ idx ] - > thridx = idx ;
ctx - > thr [ idx ] - > timeout_count = 0 ;
2012-04-13 12:47:30 +00:00
}
2013-08-23 15:28:08 +00:00
log_dbg_printf ( " Initialized %d connection handling threads \n " ,
ctx - > num_thr ) ;
2012-04-13 12:47:30 +00:00
for ( idx = 0 ; idx < ctx - > num_thr ; idx + + ) {
if ( pthread_create ( & ctx - > thr [ idx ] - > thr , NULL ,
pxy_thrmgr_thr , ctx - > thr [ idx ] ) )
goto leave_thr ;
2012-10-23 20:52:54 +00:00
while ( ! ctx - > thr [ idx ] - > running ) {
sched_yield ( ) ;
}
2012-04-13 12:47:30 +00:00
}
log_dbg_printf ( " Started %d connection handling threads \n " ,
ctx - > num_thr ) ;
2013-07-02 13:54:46 +00:00
return 0 ;
2012-04-13 12:47:30 +00:00
leave_thr :
idx - - ;
while ( idx > = 0 ) {
pthread_cancel ( ctx - > thr [ idx ] - > thr ) ;
pthread_join ( ctx - > thr [ idx ] - > thr , NULL ) ;
idx - - ;
}
2013-08-24 19:44:40 +00:00
idx = ctx - > num_thr - 1 ;
2012-04-13 12:47:30 +00:00
leave :
while ( idx > = 0 ) {
if ( ctx - > thr [ idx ] ) {
if ( ctx - > thr [ idx ] - > dnsbase ) {
evdns_base_free ( ctx - > thr [ idx ] - > dnsbase , 0 ) ;
}
if ( ctx - > thr [ idx ] - > evbase ) {
event_base_free ( ctx - > thr [ idx ] - > evbase ) ;
}
free ( ctx - > thr [ idx ] ) ;
}
idx - - ;
}
2012-10-23 20:52:54 +00:00
pthread_mutex_destroy ( & ctx - > mutex ) ;
2013-08-23 14:56:12 +00:00
if ( ctx - > thr ) {
2012-04-13 12:47:30 +00:00
free ( ctx - > thr ) ;
2013-08-23 14:56:12 +00:00
ctx - > thr = NULL ;
}
2013-07-02 13:54:46 +00:00
return - 1 ;
2012-04-13 12:47:30 +00:00
}
/*
* Destroy the event manager and stop all threads .
*/
void
pxy_thrmgr_free ( pxy_thrmgr_ctx_t * ctx )
{
pthread_mutex_destroy ( & ctx - > mutex ) ;
2013-08-23 14:56:12 +00:00
if ( ctx - > thr ) {
for ( int idx = 0 ; idx < ctx - > num_thr ; idx + + ) {
event_base_loopbreak ( ctx - > thr [ idx ] - > evbase ) ;
sched_yield ( ) ;
}
for ( int idx = 0 ; idx < ctx - > num_thr ; idx + + ) {
pthread_join ( ctx - > thr [ idx ] - > thr , NULL ) ;
}
for ( int idx = 0 ; idx < ctx - > num_thr ; idx + + ) {
2016-03-25 22:40:45 +00:00
if ( ctx - > thr [ idx ] - > dnsbase ) {
evdns_base_free ( ctx - > thr [ idx ] - > dnsbase , 0 ) ;
}
if ( ctx - > thr [ idx ] - > evbase ) {
event_base_free ( ctx - > thr [ idx ] - > evbase ) ;
}
2013-08-23 14:56:12 +00:00
free ( ctx - > thr [ idx ] ) ;
}
free ( ctx - > thr ) ;
2012-04-13 12:47:30 +00:00
}
free ( ctx ) ;
}
2017-07-10 09:27:46 +00:00
static void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_remove_conn ( pxy_conn_ctx_t * node , pxy_conn_ctx_t * * head )
2017-06-30 21:29:39 +00:00
{
assert ( node ! = NULL ) ;
assert ( * head ! = NULL ) ;
2017-07-15 01:07:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_remove_conn: DELETING, fd=%d, child_fd=%d \n " , node - > fd , node - > child_fd ) ;
2017-06-30 21:29:39 +00:00
2017-07-10 12:48:57 +00:00
// @attention We may get multiple conns with the same fd combinations, so they cannot uniquely define a conn; hence the need for uuids.
2017-06-30 21:29:39 +00:00
if ( uuid_compare ( node - > uuid , ( * head ) - > uuid , NULL ) = = 0 ) {
2017-06-29 21:38:37 +00:00
* head = ( * head ) - > next ;
return ;
}
2017-07-15 01:07:42 +00:00
pxy_conn_ctx_t * current = ( * head ) - > next ;
pxy_conn_ctx_t * previous = * head ;
2017-06-29 21:38:37 +00:00
while ( current ! = NULL & & previous ! = NULL ) {
2017-06-30 21:29:39 +00:00
if ( uuid_compare ( node - > uuid , current - > uuid , NULL ) = = 0 ) {
2017-06-29 21:38:37 +00:00
previous - > next = current - > next ;
return ;
}
previous = current ;
current = current - > next ;
}
}
2012-04-13 12:47:30 +00:00
/*
* Attach a new connection to a thread . Chooses the thread with the fewest
* currently active connections , returns the appropriate event bases .
* Returns the index of the chosen thread ( for passing to _detach later ) .
* This function cannot fail .
*/
2017-07-12 13:46:51 +00:00
void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_attach ( pxy_conn_ctx_t * ctx )
2012-04-13 12:47:30 +00:00
{
int thridx ;
size_t minload ;
2017-07-12 13:46:51 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_attach: ENTER \n " ) ;
thridx = 0 ;
2017-07-15 01:07:42 +00:00
pxy_thrmgr_ctx_t * tmctx = ctx - > thrmgr ;
pthread_mutex_lock ( & tmctx - > mutex ) ;
minload = tmctx - > thr [ thridx ] - > load ;
2012-04-13 12:47:30 +00:00
# ifdef DEBUG_THREAD
log_dbg_printf ( " ===> Proxy connection handler thread status: \n "
" thr[%d]: %zu \n " , thridx , minload ) ;
# endif /* DEBUG_THREAD */
2017-07-15 01:07:42 +00:00
for ( int idx = 1 ; idx < tmctx - > num_thr ; idx + + ) {
2012-04-13 12:47:30 +00:00
# ifdef DEBUG_THREAD
2017-07-15 01:07:42 +00:00
log_dbg_printf ( " thr[%d]: %zu \n " , idx , tmctx - > thr [ idx ] - > load ) ;
2012-04-13 12:47:30 +00:00
# endif /* DEBUG_THREAD */
2017-07-15 01:07:42 +00:00
if ( minload > tmctx - > thr [ idx ] - > load ) {
minload = tmctx - > thr [ idx ] - > load ;
2012-04-13 12:47:30 +00:00
thridx = idx ;
}
}
2017-07-15 01:07:42 +00:00
pthread_mutex_unlock ( & tmctx - > mutex ) ;
ctx - > thr = tmctx - > thr [ thridx ] ;
2017-06-29 21:38:37 +00:00
2017-07-15 01:07:42 +00:00
ctx - > evbase = ctx - > thr - > evbase ;
ctx - > dnsbase = ctx - > thr - > dnsbase ;
ctx - > thr - > load + + ;
2017-07-12 13:46:51 +00:00
2017-07-15 01:07:42 +00:00
ctx - > next = ctx - > thr - > conns ;
ctx - > thr - > conns = ctx ;
2017-06-29 21:38:37 +00:00
2017-07-10 12:48:57 +00:00
// @attention We are running on the thrmgr thread, do not call conn thread functions here.
2017-07-15 01:07:42 +00:00
//pxy_thrmgr_print_thr_info(ctx->thr);
2017-06-29 21:38:37 +00:00
2017-07-12 13:46:51 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_attach: EXIT \n " ) ;
2017-07-01 20:17:45 +00:00
# ifdef DEBUG_THREAD
log_dbg_printf ( " thridx: %d \n " , thridx ) ;
# endif /* DEBUG_THREAD */
2012-04-13 12:47:30 +00:00
}
2017-07-03 23:12:17 +00:00
void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_attach_child ( pxy_conn_ctx_t * ctx )
2017-07-03 23:12:17 +00:00
{
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_attach_child \n " ) ;
2017-07-15 01:07:42 +00:00
pthread_mutex_lock ( & ctx - > thrmgr - > mutex ) ;
ctx - > thr - > load + + ;
pthread_mutex_unlock ( & ctx - > thrmgr - > mutex ) ;
2017-07-03 23:12:17 +00:00
}
2012-04-13 12:47:30 +00:00
/*
* Detach a connection from a thread by index .
* This function cannot fail .
*/
void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_detach ( pxy_conn_ctx_t * ctx )
2012-04-13 12:47:30 +00:00
{
2017-07-15 01:07:42 +00:00
pthread_mutex_lock ( & ctx - > thrmgr - > mutex ) ;
2017-05-29 09:22:23 +00:00
2017-07-15 01:07:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_detach: BEFORE pxy_thrmgr_remove_conn \n " ) ;
pxy_thrmgr_print_thr_info ( ctx - > thr ) ;
2017-07-03 23:12:17 +00:00
2017-07-15 01:07:42 +00:00
ctx - > thr - > load - - ;
2017-06-29 21:38:37 +00:00
2017-07-15 01:07:42 +00:00
if ( ! ctx - > children ) {
pxy_thrmgr_remove_conn ( ctx , & ctx - > thr - > conns ) ;
2017-07-02 14:47:26 +00:00
} else {
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " >>>>> pxy_thrmgr_detach: parent has an active child, will not remove from the list, fd=%d, child_fd=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< \n " ,
2017-07-15 01:07:42 +00:00
ctx - > fd , ctx - > child_fd ) ;
2017-07-02 14:47:26 +00:00
}
2017-06-29 21:38:37 +00:00
2017-07-15 01:07:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " >>>>> pxy_thrmgr_detach: AFTER pxy_thrmgr_remove_conn \n " ) ;
pxy_thrmgr_print_thr_info ( ctx - > thr ) ;
2017-06-29 21:38:37 +00:00
2017-07-15 01:07:42 +00:00
pthread_mutex_unlock ( & ctx - > thrmgr - > mutex ) ;
2017-06-29 21:38:37 +00:00
}
2017-07-02 14:47:26 +00:00
void
2017-07-15 01:07:42 +00:00
pxy_thrmgr_detach_child ( pxy_conn_ctx_t * ctx )
2017-07-02 14:47:26 +00:00
{
2017-07-14 19:34:15 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " >>>>> pxy_thrmgr_detach_child \n " ) ;
2017-07-15 01:07:42 +00:00
pthread_mutex_lock ( & ctx - > thrmgr - > mutex ) ;
ctx - > thr - > load - - ;
pthread_mutex_unlock ( & ctx - > thrmgr - > mutex ) ;
2017-07-02 14:47:26 +00:00
}
2012-04-13 12:47:30 +00:00
/* vim: set noet ft=c: */