mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 09:25:49 +08:00
Event loops: started once when services' first clients come at once
loopsstart() runs on the thread of the service whose client is the first one to be served on a loop, not on the configuration's thread: two services given their first clients at the same time could each initialize its mutex, take it, and start loops of their own. A loop of the second array was then given to a thread of the first one as well: two threads ran one loop, and its timers and fibers were taken by both (crashes in the timers' heap, seen on Windows under load). The mutex is a global one now, made at startup with the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
97ab683654
commit
63cfcafbc5
@ -491,6 +491,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
|
||||
_3proxy_mutex_init(&bandlim_mutex);
|
||||
_3proxy_mutex_init(&connlim_mutex);
|
||||
_3proxy_mutex_init(&tc_mutex);
|
||||
_3proxy_mutex_init(&loops_mutex);
|
||||
_3proxy_mutex_init(&tpool.mutex);
|
||||
#ifndef NORADIUS
|
||||
_3proxy_mutex_init(&rad_mutex);
|
||||
|
||||
@ -37,6 +37,8 @@ void transparent_install(void);
|
||||
_3proxy_mutex_t bandlim_mutex;
|
||||
_3proxy_mutex_t connlim_mutex;
|
||||
_3proxy_mutex_t tc_mutex;
|
||||
/* the event loops, started by the first client served on one */
|
||||
_3proxy_mutex_t loops_mutex;
|
||||
_3proxy_mutex_t config_mutex;
|
||||
int runningservices = 0;
|
||||
_3proxy_mutex_t runningservices_mutex;
|
||||
|
||||
@ -85,8 +85,6 @@ struct loopjob {
|
||||
static struct looper *loopers;
|
||||
static unsigned nloopers, nextlooper;
|
||||
static int loopsfailed;
|
||||
static _3proxy_mutex_t loopers_mutex;
|
||||
static int loopers_mutex_init;
|
||||
|
||||
/* the loop of this thread, NULL but in a loop's thread */
|
||||
static LTLS struct looper *curlooper;
|
||||
@ -1111,20 +1109,17 @@ static int loopsstart(void){
|
||||
|
||||
if(nloopers) return 0;
|
||||
if(loopsfailed) return 1;
|
||||
if(!loopers_mutex_init){
|
||||
/* the first services start from the configuration's thread */
|
||||
_3proxy_mutex_init(&loopers_mutex);
|
||||
loopers_mutex_init = 1;
|
||||
}
|
||||
_3proxy_mutex_lock(&loopers_mutex);
|
||||
/* the first clients of services may come at once, each from the
|
||||
thread of its service */
|
||||
_3proxy_mutex_lock(&loops_mutex);
|
||||
if(nloopers || loopsfailed){
|
||||
_3proxy_mutex_unlock(&loopers_mutex);
|
||||
_3proxy_mutex_unlock(&loops_mutex);
|
||||
return loopsfailed;
|
||||
}
|
||||
n = runconf->loops? (unsigned)runconf->loops : ncpus();
|
||||
if(!fiberusable() || !(loopers = calloc(n, sizeof(*loopers)))){
|
||||
loopsfailed = 1;
|
||||
_3proxy_mutex_unlock(&loopers_mutex);
|
||||
_3proxy_mutex_unlock(&loops_mutex);
|
||||
return 1;
|
||||
}
|
||||
for(i = 0; i < n; i++){
|
||||
@ -1166,7 +1161,7 @@ static int loopsstart(void){
|
||||
#endif
|
||||
fiberpollfunc = fiberpoll;
|
||||
}
|
||||
_3proxy_mutex_unlock(&loopers_mutex);
|
||||
_3proxy_mutex_unlock(&loops_mutex);
|
||||
return !i;
|
||||
}
|
||||
|
||||
@ -1196,9 +1191,9 @@ static struct loopjob *loopjobnew(size_t stacksize){
|
||||
static void loopspawn(struct loopjob *job, struct clientparam *param){
|
||||
struct looper *lp;
|
||||
|
||||
_3proxy_mutex_lock(&loopers_mutex);
|
||||
_3proxy_mutex_lock(&loops_mutex);
|
||||
lp = loopers + (nextlooper++ % nloopers);
|
||||
_3proxy_mutex_unlock(&loopers_mutex);
|
||||
_3proxy_mutex_unlock(&loops_mutex);
|
||||
job->param = param;
|
||||
looppost(&lp->l, &job->m);
|
||||
}
|
||||
|
||||
@ -611,6 +611,7 @@ extern _3proxy_sem_t serviceexited;
|
||||
extern _3proxy_mutex_t bandlim_mutex;
|
||||
extern _3proxy_mutex_t connlim_mutex;
|
||||
extern _3proxy_mutex_t tc_mutex;
|
||||
extern _3proxy_mutex_t loops_mutex;
|
||||
extern _3proxy_mutex_t log_mutex;
|
||||
extern _3proxy_mutex_t rad_mutex;
|
||||
extern struct datatype datatypes[64];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user