mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-15 16:15:49 +08:00
Change waiting loops to semaphores for child counters
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
This commit is contained in:
parent
a090ac8cd8
commit
98e8dfb004
@ -415,11 +415,12 @@ set(3PROXY_CORE_SOURCES
|
||||
# Object libraries for common sources (shared between executables)
|
||||
# ============================================================================
|
||||
|
||||
# Common object library (sockmap, sockgetchar, common, log)
|
||||
# Common object library (sockmap, sockgetchar, common, sem, log)
|
||||
add_library(common_obj OBJECT
|
||||
src/sockmap.c
|
||||
src/sockgetchar.c
|
||||
src/common.c
|
||||
src/sem.c
|
||||
src/log.c
|
||||
)
|
||||
target_include_directories(common_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
@ -13,6 +13,9 @@ udpsockmap$(OBJSUFFICS): udpsockmap.c proxy.h structures.h
|
||||
common$(OBJSUFFICS): common.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) common.c
|
||||
|
||||
sem$(OBJSUFFICS): sem.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) sem.c
|
||||
|
||||
plugins$(OBJSUFFICS): plugins.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) plugins.c
|
||||
|
||||
@ -56,32 +59,32 @@ socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c
|
||||
3proxy$(OBJSUFFICS): 3proxy.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) 3proxy.c
|
||||
|
||||
$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||
$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
||||
|
||||
mainfunc$(OBJSUFFICS): proxy.h structures.h proxymain.c
|
||||
$(CC) $(COUT)mainfunc$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)MODULEMAINFUNC=mainfunc proxymain.c
|
||||
@ -194,6 +197,6 @@ ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h
|
||||
pcre$(OBJSUFFICS): pcre.c structures.h
|
||||
$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c
|
||||
|
||||
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(VERSIONDEP)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
|
||||
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(VERSIONDEP)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
|
||||
|
||||
|
||||
27
src/common.c
27
src/common.c
@ -187,33 +187,6 @@ size_t threadstacksize(int extra){
|
||||
if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN;
|
||||
return (size_t)size;
|
||||
}
|
||||
|
||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount){
|
||||
sem->count = count;
|
||||
sem->maxcount = maxcount;
|
||||
if(pthread_mutex_init(&sem->mutex, NULL)) return 1;
|
||||
if(pthread_cond_init(&sem->cond, NULL)){
|
||||
pthread_mutex_destroy(&sem->mutex);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _3proxy_sem_lock_f(_3proxy_sem_t *sem){
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
while(!sem->count) pthread_cond_wait(&sem->cond, &sem->mutex);
|
||||
sem->count--;
|
||||
pthread_mutex_unlock(&sem->mutex);
|
||||
}
|
||||
|
||||
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem){
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
if(sem->count < sem->maxcount){
|
||||
sem->count++;
|
||||
pthread_cond_signal(&sem->cond);
|
||||
}
|
||||
pthread_mutex_unlock(&sem->mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct extparam conf = {
|
||||
|
||||
14
src/proxy.h
14
src/proxy.h
@ -322,13 +322,23 @@ extern _3proxy_sem_t udpinit;
|
||||
#define _3proxy_sem_init(x, count, maxcount) (((x) = CreateSemaphore(NULL, (count), (maxcount), NULL))? 0 : 1)
|
||||
#define _3proxy_sem_lock(x) WaitForSingleObject(x, INFINITE)
|
||||
#define _3proxy_sem_unlock(x) ReleaseSemaphore(x, 1, NULL)
|
||||
#define _3proxy_sem_init_timed(x, count, maxcount) _3proxy_sem_init(x, (count), (maxcount))
|
||||
#define _3proxy_sem_timedlock(x, ms) (WaitForSingleObject(x, ms) != WAIT_OBJECT_0)
|
||||
#define _3proxy_sem_destroy(x) CloseHandle(x)
|
||||
#else
|
||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount);
|
||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount, int timed);
|
||||
void _3proxy_sem_lock_f(_3proxy_sem_t *sem);
|
||||
int _3proxy_sem_timedlock_f(_3proxy_sem_t *sem, unsigned ms);
|
||||
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem);
|
||||
#define _3proxy_sem_init(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount))
|
||||
void _3proxy_sem_destroy_f(_3proxy_sem_t *sem);
|
||||
#define _3proxy_sem_init(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount), 0)
|
||||
/* for a semaphore waited on with a timeout: the wait is not stretched or cut
|
||||
short by the system time being changed, where the platform allows it */
|
||||
#define _3proxy_sem_init_timed(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount), 1)
|
||||
#define _3proxy_sem_lock(x) _3proxy_sem_lock_f(&x)
|
||||
#define _3proxy_sem_timedlock(x, ms) _3proxy_sem_timedlock_f(&x, (ms))
|
||||
#define _3proxy_sem_unlock(x) _3proxy_sem_unlock_f(&x)
|
||||
#define _3proxy_sem_destroy(x) _3proxy_sem_destroy_f(&x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -308,6 +308,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
FILE *fp = NULL;
|
||||
struct linger lg;
|
||||
int nlog = 5000;
|
||||
int haveslot = 0, nfull = 0;
|
||||
#ifdef __linux__
|
||||
int saved_nsfd = -1;
|
||||
#endif
|
||||
@ -990,14 +991,19 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
|
||||
for (;;) {
|
||||
for(;;){
|
||||
while((conf.paused == srv.paused && srv.childcount >= srv.maxchild)){
|
||||
nlog++;
|
||||
if(!srv.silent && nlog > 5000) {
|
||||
/* A connection is only taken with a slot of maxchild in hand, which
|
||||
goes to its child; a slot not handed on is kept for the next one.
|
||||
The wait is timed to notice a reload. */
|
||||
while(!haveslot && conf.paused == srv.paused){
|
||||
if(!_3proxy_sem_timedlock(srv.childslots, 1000)){
|
||||
haveslot = 1;
|
||||
nfull = 0;
|
||||
break;
|
||||
}
|
||||
if(!srv.silent && !(nfull++ % 5)) {
|
||||
sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
|
||||
dolog(&defparam, buf);
|
||||
nlog = 0;
|
||||
}
|
||||
usleep(SLEEPTIME);
|
||||
}
|
||||
if (iscbc) break;
|
||||
if (conf.paused != srv.paused) break;
|
||||
@ -1213,6 +1219,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
}
|
||||
else {
|
||||
srv.childcount++;
|
||||
haveslot = 0;
|
||||
newparam->threadid = (uint64_t)thread;
|
||||
}
|
||||
_3proxy_mutex_unlock(&srv.counter_mutex);
|
||||
@ -1230,6 +1237,8 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
#endif
|
||||
|
||||
if(!srv.silent) srv.logfunc(&defparam, (unsigned char *)"Exiting thread");
|
||||
/* srvfree() waits for every slot to come back, this one included */
|
||||
if(haveslot) _3proxy_sem_unlock(srv.childslots);
|
||||
srvfree(&srv);
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -1284,6 +1293,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
||||
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
||||
*SAFAMILY(¶m->req) = *SAFAMILY(¶m->sinsl) = *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->sincr) = *SAFAMILY(¶m->sincl) = AF_INET;
|
||||
_3proxy_mutex_init(&srv->counter_mutex);
|
||||
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
||||
#ifndef NOUDPMAIN
|
||||
if(!udpinited){
|
||||
(void)_3proxy_sem_init(udpinit, 1, 1);
|
||||
@ -1329,6 +1339,8 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){
|
||||
}
|
||||
|
||||
void srvfree(struct srvparam * srv){
|
||||
int i;
|
||||
|
||||
if(srv->srvsock != INVALID_SOCKET) {
|
||||
so._closesocket(srv->so.state, srv->srvsock);
|
||||
#ifdef WITH_UN
|
||||
@ -1339,16 +1351,13 @@ void srvfree(struct srvparam * srv){
|
||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||
srv->cbsock = INVALID_SOCKET;
|
||||
srv->service = S_ZOMBIE;
|
||||
/* under the mutex, so the last child has let go of it before it is destroyed */
|
||||
for(;;){
|
||||
struct clientparam *child;
|
||||
|
||||
_3proxy_mutex_lock(&srv->counter_mutex);
|
||||
child = srv->child;
|
||||
_3proxy_mutex_unlock(&srv->counter_mutex);
|
||||
if(!child) break;
|
||||
usleep(SLEEPTIME * 100);
|
||||
}
|
||||
/* Every child returns its slot as the last thing it does with the service,
|
||||
so once all of them are back no child is left. A child posts its slot
|
||||
holding the mutex: taking the mutex once more waits for the last one to
|
||||
have let go of both before they are destroyed. */
|
||||
for(i = srv->maxchild; i; i--) _3proxy_sem_lock(srv->childslots);
|
||||
_3proxy_mutex_lock(&srv->counter_mutex);
|
||||
_3proxy_mutex_unlock(&srv->counter_mutex);
|
||||
#ifndef STDMAIN
|
||||
if(srv->filter){
|
||||
while(srv->nfilters){
|
||||
@ -1367,6 +1376,7 @@ void srvfree(struct srvparam * srv){
|
||||
if(srv->authfuncs)freeauth(srv->authfuncs);
|
||||
#endif
|
||||
_3proxy_mutex_destroy(&srv->counter_mutex);
|
||||
_3proxy_sem_destroy(srv->childslots);
|
||||
if(srv->target) free(srv->target);
|
||||
if(srv->logtarget) free(srv->logtarget);
|
||||
if(srv->logformat) free(srv->logformat);
|
||||
@ -1454,6 +1464,9 @@ void freeparam(struct clientparam * param) {
|
||||
param->next->prev = param->prev;
|
||||
}
|
||||
(param->srv->childcount)--;
|
||||
/* under the mutex too: srvfree() may destroy the semaphore as
|
||||
soon as the mutex shows the last child gone */
|
||||
_3proxy_sem_unlock(param->srv->childslots);
|
||||
}
|
||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||
}
|
||||
|
||||
110
src/sem.c
Normal file
110
src/sem.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
3APA3A simplest proxy server
|
||||
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
|
||||
|
||||
please read License Agreement
|
||||
|
||||
*/
|
||||
|
||||
/* Counting semaphores for POSIX systems, built on a mutex and a condition
|
||||
variable: unnamed POSIX semaphores are not available everywhere (macOS)
|
||||
and have no timed wait there. Windows uses its own semaphores, see proxy.h. */
|
||||
|
||||
#include "proxy.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
/* macOS has CLOCK_MONOTONIC but no pthread_condattr_setclock(); a relative
|
||||
wait is used there instead, which the system time does not affect either */
|
||||
#if defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
|
||||
#define SEM_MONOTONIC
|
||||
#endif
|
||||
|
||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount, int timed){
|
||||
int res;
|
||||
|
||||
sem->count = count;
|
||||
sem->maxcount = maxcount;
|
||||
sem->monotonic = 0;
|
||||
if(pthread_mutex_init(&sem->mutex, NULL)) return 1;
|
||||
#ifdef SEM_MONOTONIC
|
||||
if(timed){
|
||||
pthread_condattr_t attr;
|
||||
|
||||
if(!pthread_condattr_init(&attr)){
|
||||
if(!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) sem->monotonic = 1;
|
||||
res = pthread_cond_init(&sem->cond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
}
|
||||
else res = pthread_cond_init(&sem->cond, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
res = pthread_cond_init(&sem->cond, NULL);
|
||||
if(res){
|
||||
pthread_mutex_destroy(&sem->mutex);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _3proxy_sem_lock_f(_3proxy_sem_t *sem){
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
while(!sem->count) pthread_cond_wait(&sem->cond, &sem->mutex);
|
||||
sem->count--;
|
||||
pthread_mutex_unlock(&sem->mutex);
|
||||
}
|
||||
|
||||
/* Returns 0 with the semaphore taken, nonzero if ms passed first. */
|
||||
int _3proxy_sem_timedlock_f(_3proxy_sem_t *sem, unsigned ms){
|
||||
struct timespec ts;
|
||||
int res = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (long)(ms % 1000) * 1000000;
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
while(!sem->count && !res) res = pthread_cond_timedwait_relative_np(&sem->cond, &sem->mutex, &ts);
|
||||
#else
|
||||
/* the deadline is on the clock the condition variable was set up with */
|
||||
#ifdef SEM_MONOTONIC
|
||||
if(sem->monotonic) clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
}
|
||||
ts.tv_sec += ms / 1000;
|
||||
ts.tv_nsec += (long)(ms % 1000) * 1000000;
|
||||
if(ts.tv_nsec >= 1000000000){
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000;
|
||||
}
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
while(!sem->count && !res) res = pthread_cond_timedwait(&sem->cond, &sem->mutex, &ts);
|
||||
#endif
|
||||
if(sem->count){
|
||||
sem->count--;
|
||||
res = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&sem->mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem){
|
||||
pthread_mutex_lock(&sem->mutex);
|
||||
if(sem->count < sem->maxcount){
|
||||
sem->count++;
|
||||
pthread_cond_signal(&sem->cond);
|
||||
}
|
||||
pthread_mutex_unlock(&sem->mutex);
|
||||
}
|
||||
|
||||
void _3proxy_sem_destroy_f(_3proxy_sem_t *sem){
|
||||
pthread_cond_destroy(&sem->cond);
|
||||
pthread_mutex_destroy(&sem->mutex);
|
||||
}
|
||||
#endif
|
||||
@ -47,6 +47,7 @@ typedef struct _3proxy_sem_s {
|
||||
pthread_cond_t cond;
|
||||
unsigned count;
|
||||
unsigned maxcount;
|
||||
int monotonic; /* timed waits measured on CLOCK_MONOTONIC */
|
||||
} _3proxy_sem_t;
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
@ -635,6 +636,7 @@ struct srvparam {
|
||||
#endif
|
||||
PROXYSOCKADDRTYPE extsa;
|
||||
_3proxy_mutex_t counter_mutex;
|
||||
_3proxy_sem_t childslots; /* maxchild of them, one held by each child */
|
||||
struct pollfd fds;
|
||||
FILE *stdlog;
|
||||
unsigned char * target;
|
||||
|
||||
@ -69,7 +69,7 @@ means to stand on its own should start with one - otherwise an earlier
|
||||
|
||||
## What is not covered yet
|
||||
|
||||
41 of the 112 configuration commands appear in a test, and the count says
|
||||
42 of the 112 configuration commands appear in a test, and the count says
|
||||
nothing about service options: the IPv6 case, for instance, exercises -4,
|
||||
-6, -46, -64 and -i without adding a command to it. What follows is
|
||||
roughly the order worth working through: how much of the product a gap
|
||||
@ -78,12 +78,13 @@ covers, and how much of a fixture it needs.
|
||||
### Traffic limits and accounting
|
||||
|
||||
`bandlimin` `bandlimout` `nobandlimin` `nobandlimout` `connlim` `noconnlim`
|
||||
`countin` `countout` `countall` and the `no*` forms, `maxconn`.
|
||||
`countin` `countout` `countall` and the `no*` forms.
|
||||
|
||||
Cheap and worth doing first: `data?size=` and a stopwatch measure a
|
||||
bandwidth limit, and the admin counters page already shows what a counter
|
||||
holds. `countin` appears in a configuration today but nothing checks that it
|
||||
counts. `connlim` and `maxconn` need concurrent connections.
|
||||
counts. `connlim` needs concurrent connections, held open the way the
|
||||
`maxconn` case holds them.
|
||||
|
||||
### The mail proxies
|
||||
|
||||
|
||||
107
tests/cases/maxconn.py
Normal file
107
tests/cases/maxconn.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""maxconn: a service serves at most that many connections at once, and a
|
||||
connection over the limit waits for one of them to finish."""
|
||||
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import time
|
||||
|
||||
|
||||
def run(t):
|
||||
# The origin runs in a process of its own, so the limit only applies to
|
||||
# the mapper in front of it.
|
||||
origin = t.free_port()
|
||||
t.start("maxconn_origin", f"""
|
||||
auth iponly
|
||||
allow *
|
||||
http echo * /echo**
|
||||
httpsrv -p{origin}
|
||||
""", ports=[origin])
|
||||
|
||||
mapped = t.free_port()
|
||||
server = t.start("maxconn", f"""
|
||||
log
|
||||
maxconn 2
|
||||
auth iponly
|
||||
allow *
|
||||
tcppm {mapped} 127.0.0.1 {origin}
|
||||
""", ports=[mapped])
|
||||
|
||||
def connect():
|
||||
sock = socket.create_connection(("127.0.0.1", mapped), 5)
|
||||
opened.append(sock)
|
||||
return sock
|
||||
|
||||
def served(sock, timeout):
|
||||
"""Ask over a kept alive connection; True once the whole reply is in,
|
||||
so the connection is ready for the next request."""
|
||||
sock.sendall(b"GET /echo HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n")
|
||||
sock.settimeout(timeout)
|
||||
data = b""
|
||||
try:
|
||||
while b"\r\n\r\n" not in data:
|
||||
chunk = sock.recv(4096)
|
||||
if not chunk:
|
||||
return False
|
||||
data += chunk
|
||||
head, body = data.split(b"\r\n\r\n", 1)
|
||||
length = 0
|
||||
for line in head.split(b"\r\n")[1:]:
|
||||
name, _, value = line.partition(b":")
|
||||
if name.strip().lower() == b"content-length":
|
||||
length = int(value)
|
||||
while len(body) < length:
|
||||
chunk = sock.recv(4096)
|
||||
if not chunk:
|
||||
return False
|
||||
body += chunk
|
||||
return head.startswith(b"HTTP/1.1 200")
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
opened = []
|
||||
try:
|
||||
# the probe that saw the port open holds a slot until its session
|
||||
# ends, so wait for both slots to be free before taking them
|
||||
deadline = time.time() + 5
|
||||
while True:
|
||||
first, second = connect(), connect()
|
||||
both = served(first, 1) and served(second, 1)
|
||||
if both or time.time() > deadline:
|
||||
break
|
||||
first.close()
|
||||
second.close()
|
||||
t.eq(True, both, "two connections are served under maxconn 2")
|
||||
|
||||
third = connect()
|
||||
t.eq(False, served(third, 1.5),
|
||||
"a third connection waits while both slots are held")
|
||||
t.contains(t.wait_output(server, "too many connected clients"),
|
||||
"too many connected clients",
|
||||
"a service at its limit says so in the log")
|
||||
|
||||
first.close()
|
||||
t.eq(True, served(third, 5),
|
||||
"the waiting connection is served once a slot is freed")
|
||||
t.eq(True, served(second, 5),
|
||||
"a connection holding a slot keeps being served")
|
||||
|
||||
if os.name == "nt":
|
||||
t.skip("reload while at the limit (no SIGUSR1 on Windows)")
|
||||
else:
|
||||
waiting = connect()
|
||||
t.eq(False, served(waiting, 1),
|
||||
"the limit holds again with two connections open")
|
||||
server.proc.send_signal(signal.SIGUSR1)
|
||||
# A connection made the instant the signal arrives can land on
|
||||
# the listener being replaced and be reset; give the new service
|
||||
# the moment it needs.
|
||||
time.sleep(1.5)
|
||||
fresh = connect()
|
||||
t.eq(True, served(fresh, 5),
|
||||
"a reload while the limit is reached starts a service with "
|
||||
"its slots free")
|
||||
t.eq(None, server.proc.poll(), "the process survives the reload")
|
||||
finally:
|
||||
for sock in opened:
|
||||
sock.close()
|
||||
Loading…
Reference in New Issue
Block a user