Zhuang Yuyao wrote:
I am still trying to find another better solution: let kernel to send stunnel a signal while available memory is under a special threshold, then stunnel will stop accepting new connections and try to release some memory (kill the latest created threads?) until kernel notifies us the available memory is increased and enough for new connections/threads.
Sounds like a crazy idea to me. 8-)
Monitoring available memory creates an obvious race condition (with other processes using the same memory) unless you're going to do it in kernel. 8-)))
BTW: Stunnel itself should work fine with OOM killer turned off. I'm not so sure about its libraries.
$ egrep -A 2 '(malloc)|(calloc)|(realloc)' *.c client.c: c=calloc(1, sizeof(CLI)); client.c- if(!c) { client.c- s_log(LOG_ERR, "Memory allocation failed"); -- ctx.c: cp=malloc(n+1); ctx.c- n=BIO_read(bio, cp, n); ctx.c- cp[n]='\0'; -- file.c: df=calloc(1, sizeof(DISK_FILE)); file.c- if(!df) file.c- return NULL; -- file.c: df=calloc(1, sizeof(DISK_FILE)); file.c- if(!df) file.c- return NULL; -- file.c: buff=calloc(len+2, 1); /* +2 for \r\n */ file.c- if(!buff) file.c- return 0; -- file.c: out=malloc((len+1)*sizeof(WCHAR)); file.c- if(!out) file.c- return NULL; -- file.c: out=malloc(len+1); file.c- if(!out) file.c- return NULL; -- file.c: out=malloc(len+1); file.c- if(!out) file.c- return NULL; -- file.c: out=malloc(len+1); file.c- if(!out) file.c- return NULL; -- gui.c: curr=malloc(sizeof(struct LIST)+len*sizeof(TCHAR)); gui.c- curr->len=len; gui.c- _tcscpy(curr->txt, txt); -- gui.c: buff=malloc((len+1)*sizeof(TCHAR)); /* +1 for trailing '\0' */ gui.c- for(curr=head; curr; curr=curr->next) { gui.c- memcpy(buff+ptr, curr->txt, curr->len*sizeof(TCHAR)); -- network.c: ufds=realloc(ufds, nfds*sizeof(struct pollfd)); network.c- if(!ufds) { network.c- s_log(LOG_CRIT, "Memory allocation failed"); -- options.c: new_section=calloc(1, sizeof(LOCAL_OPTIONS)); options.c- if(!new_section) { options.c- log_raw("Fatal memory allocation error"); -- options.c: retval=calloc(strlen(str)+1, 1); options.c- if(!retval) { options.c- log_raw("Fatal memory allocation error"); -- options.c: retval=calloc(len+1, 1); options.c- if(!retval) { options.c- log_raw("Fatal memory allocation error"); -- options.c: retval=calloc(max_arg+1, sizeof(char *)); options.c- if(!retval) { options.c- log_raw("Fatal memory allocation error"); -- options.c: ptr->opt_val[socket_type]=calloc(1, sizeof(OPT_UNION)); options.c- switch(ptr->opt_type) { options.c- case TYPE_FLAG: -- resolver.c: ai=calloc(1, sizeof(struct addrinfo)); resolver.c- if(!ai) resolver.c- return EAI_MEMORY; -- resolver.c: ai->ai_addr=calloc(1, ai->ai_addrlen); resolver.c- if(!ai->ai_addr) { resolver.c- free(ai); -- resolver.c: ai->ai_addr=calloc(1, ai->ai_addrlen); resolver.c- if(!ai->ai_addr) { resolver.c- free(ai); -- resolver.c: ai=calloc(1, sizeof(struct addrinfo)); resolver.c- if(!ai) resolver.c- return EAI_MEMORY; -- resolver.c: ai->ai_addr=calloc(1, ai->ai_addrlen); resolver.c- if(!ai->ai_addr) resolver.c- return EAI_MEMORY; -- resolver.c: ai->ai_addr=calloc(1, ai->ai_addrlen); resolver.c- if(!ai->ai_addr) resolver.c- return EAI_MEMORY; -- sthreads.c: ctx=malloc(sizeof(CONTEXT)); sthreads.c- if(!ctx) { sthreads.c- s_log(LOG_ERR, "Unable to allocate CONTEXT structure");
Best regards, Mike