mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
Reattach: a new service's slot for its next client taken before it is found
A TCP service keeps one of its maxconn slots for the next client it accepts, but took it only once its thread reached the accept loop. A reload puts the new service on its listener (mainclaim(), in the thread reading the configuration) before its thread even starts, and the clients of the old services move to it as soon as they see it there: in that window they could take every slot, the one it keeps included. The reattach test, with maxconn 2, then had both of two downloads go on instead of one, now and then on a loaded runner, every time with a 300 ms sleep put in the window. mainclaim() takes the slot first; srvrun() takes it over, and srvdiscard() gives it back for a service which never ran. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2052dc0a4f
commit
7fab9c488d
@ -152,6 +152,11 @@ static void srvstrings(struct srvstart *s){
|
||||
|
||||
/* Releases what the preparation and the run took, s itself excepted. */
|
||||
static void srvdiscard(struct srvstart *s){
|
||||
/* a slot taken for a service which never ran: srvfree() waits for all */
|
||||
if(s->haveslot){
|
||||
_3proxy_sem_unlock(s->srv.childslots);
|
||||
s->haveslot = 0;
|
||||
}
|
||||
srvfree(&s->srv);
|
||||
srvstrings(s);
|
||||
}
|
||||
@ -245,6 +250,7 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
||||
|
||||
s->cbc_string = s->cbl_string = NULL;
|
||||
s->iscbc = s->iscbl = 0;
|
||||
s->haveslot = 0;
|
||||
#ifdef STDMAIN
|
||||
#ifndef _WIN32
|
||||
s->inetd = 0;
|
||||
|
||||
@ -374,6 +374,11 @@ void mainclaim(void *service){
|
||||
struct srvparam *srv = &s->srv;
|
||||
struct listener *l, *found = NULL, *newl;
|
||||
|
||||
/* The slot it keeps for its next client taken first: once on the
|
||||
listener, it is where the clients of older services move after a reload
|
||||
(reattach()), which must find that slot taken, as it is once the service
|
||||
accepts, and not take more than the others of its maxconn. */
|
||||
if(!s->isudp && !s->haveslot && !_3proxy_sem_timedlock(srv->childslots, 0)) s->haveslot = 1;
|
||||
/* made beforehand, as the mutex is held from finding a listener to
|
||||
joining it, lest its last service let go of it meanwhile */
|
||||
if((newl = malloc(sizeof(*newl)))){
|
||||
|
||||
@ -26,6 +26,9 @@ struct srvstart {
|
||||
struct clientparam defparam;
|
||||
unsigned char *cbc_string, *cbl_string;
|
||||
int isudp, iscbc, iscbl;
|
||||
/* the slot a TCP service keeps for its next client, taken before it can
|
||||
be found on its listener: srvrun() takes it over */
|
||||
int haveslot;
|
||||
const struct udpservice *udp;
|
||||
#ifndef _WIN32
|
||||
pthread_attr_t pa;
|
||||
@ -121,9 +124,11 @@ static int srvrun(struct srvstart *s);
|
||||
static int srvrun(struct srvstart *s){
|
||||
struct srvparam *srv = &s->srv;
|
||||
struct clientparam *defparam = &s->defparam;
|
||||
int res = 0, haveslot = 0;
|
||||
int res = 0, haveslot = s->haveslot;
|
||||
/* -r: a TCP service connects out for each client instead of listening */
|
||||
int connectback = !s->isudp && s->iscbc;
|
||||
|
||||
s->haveslot = 0;
|
||||
#ifndef _WIN32
|
||||
pthread_attr_init(&s->pa);
|
||||
pthread_attr_setstacksize(&s->pa,threadstacksize(srv->stacksize));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user