Services: threadperclient, a thread for each client where one is needed

A flag of the service for what cannot share a thread between clients,
once clients can be served otherwise: what waits other than in
sockpoll(), or a thread which may be unable to serve another client.
It is set for a service
- with FilePlugin, whose _prepoll writes files and sends them;
- with a -ne network namespace: a thread which failed to come back from
  it to the main namespace is not to serve another client;
- writing to an ODBC log, should the log have no thread of its own to
  write it: struct logtype has blocks, for a log waiting other than in
  sockpoll().

Nothing serves clients otherwise yet: as before, each has a thread.

Incompatible for plugins, which have to be built again with the same
version of 3proxy: struct srvparam has threadperclient, struct logtype
has blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-24 19:54:03 +03:00
parent b4bbcb9e9a
commit 3e7f749eb6
4 changed files with 12 additions and 1 deletions

View File

@ -632,7 +632,11 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
if(srv->i_nsfd >= 0 && (setns(srv->i_nsfd, CLONE_NEWNET) || setns(mainnsfd, CLONE_NEWNET))) return 4;
if(srv->o_nsfd >= 0 && (setns(srv->o_nsfd, CLONE_NEWNET) || setns(mainnsfd, CLONE_NEWNET))) return 4;
}
/* a thread which could not come back from the -ne namespace serves no
other client */
if(srv->o_nsfd >= 0) srv->threadperclient = 1;
#endif
if(srv->logger && srv->logger->type && srv->logger->type->blocks) srv->threadperclient = 1;
#ifndef STDMAIN
if((error = copyfilter(conf->filters, srv))) return error;

View File

@ -767,7 +767,10 @@ static int fp_registercallback (int what, int max_size, int preview_size, struct
}
/* Its _prepoll writes the files and sends them: the service's clients each
have a thread. */
static void * fp_open(void * idata, struct srvparam * param){
param->threadperclient = 1;
return idata;
}

View File

@ -132,7 +132,7 @@ static void odbcclose(struct logger *lg){
}
const struct logtype logtype_odbc = {
"odbc", odbcmatch, odbcinit, odbcformat, odbcwrite, odbcclose, NULL, LOGSTACKSIZE, 0, 0, 1
"odbc", odbcmatch, odbcinit, odbcformat, odbcwrite, odbcclose, NULL, LOGSTACKSIZE, 0, 0, 1, 1
};
#endif

View File

@ -667,6 +667,7 @@ struct logtype {
int standard; /* kept open for the life of the process */
int text; /* writes a line of text: errors can go there */
int params; /* the string after a comma is parameters */
int blocks; /* waits for its writes other than in sockpoll() */
};
/* What a log's queue holds: a line (log.c's struct logslot, of which this
@ -746,6 +747,9 @@ struct srvparam {
int family;
int resolvmode; /* RESOLVE_* */
int stacksize;
/* a thread for each client: what serves them waits other than in
sockpoll(), or must not be left by a thread to serve another */
int threadperclient;
struct extparam *config; /* the configuration it was started with */
int timeouts[12]; /* conf.timeouts as they were when the service started */
int filtermaxsize, parentretries, maxseg; /* and these */