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. */
|
/* Releases what the preparation and the run took, s itself excepted. */
|
||||||
static void srvdiscard(struct srvstart *s){
|
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);
|
srvfree(&s->srv);
|
||||||
srvstrings(s);
|
srvstrings(s);
|
||||||
}
|
}
|
||||||
@ -245,6 +250,7 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
|||||||
|
|
||||||
s->cbc_string = s->cbl_string = NULL;
|
s->cbc_string = s->cbl_string = NULL;
|
||||||
s->iscbc = s->iscbl = 0;
|
s->iscbc = s->iscbl = 0;
|
||||||
|
s->haveslot = 0;
|
||||||
#ifdef STDMAIN
|
#ifdef STDMAIN
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
s->inetd = 0;
|
s->inetd = 0;
|
||||||
|
|||||||
@ -374,6 +374,11 @@ void mainclaim(void *service){
|
|||||||
struct srvparam *srv = &s->srv;
|
struct srvparam *srv = &s->srv;
|
||||||
struct listener *l, *found = NULL, *newl;
|
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
|
/* made beforehand, as the mutex is held from finding a listener to
|
||||||
joining it, lest its last service let go of it meanwhile */
|
joining it, lest its last service let go of it meanwhile */
|
||||||
if((newl = malloc(sizeof(*newl)))){
|
if((newl = malloc(sizeof(*newl)))){
|
||||||
|
|||||||
@ -26,6 +26,9 @@ struct srvstart {
|
|||||||
struct clientparam defparam;
|
struct clientparam defparam;
|
||||||
unsigned char *cbc_string, *cbl_string;
|
unsigned char *cbc_string, *cbl_string;
|
||||||
int isudp, iscbc, iscbl;
|
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;
|
const struct udpservice *udp;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pthread_attr_t pa;
|
pthread_attr_t pa;
|
||||||
@ -121,9 +124,11 @@ static int srvrun(struct srvstart *s);
|
|||||||
static int srvrun(struct srvstart *s){
|
static int srvrun(struct srvstart *s){
|
||||||
struct srvparam *srv = &s->srv;
|
struct srvparam *srv = &s->srv;
|
||||||
struct clientparam *defparam = &s->defparam;
|
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 */
|
/* -r: a TCP service connects out for each client instead of listening */
|
||||||
int connectback = !s->isudp && s->iscbc;
|
int connectback = !s->isudp && s->iscbc;
|
||||||
|
|
||||||
|
s->haveslot = 0;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pthread_attr_init(&s->pa);
|
pthread_attr_init(&s->pa);
|
||||||
pthread_attr_setstacksize(&s->pa,threadstacksize(srv->stacksize));
|
pthread_attr_setstacksize(&s->pa,threadstacksize(srv->stacksize));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user