extern int stopping; /* non zero means stopping in progress */
extern char hostname[MAX_HOSTNAME_LEN];
extern char localpeer[MAX_HOSTNAME_LEN];
+extern struct list global_listener_queue; /* list of the temporarily limited listeners */
#endif /* _TYPES_GLOBAL_H */
char hostname[MAX_HOSTNAME_LEN];
char localpeer[MAX_HOSTNAME_LEN];
+/* list of the temporarily limited listeners because of lack of resource */
+struct list global_listener_queue = LIST_HEAD_INIT(global_listener_queue);
/*********************************************************************/
/* general purpose functions ***************************************/
if (s->listener->state == LI_FULL)
resume_listener(s->listener);
+ /* Dequeues all of the listeners waiting for a resource */
+ if (!LIST_ISEMPTY(&global_listener_queue))
+ dequeue_all_listeners(&global_listener_queue);
+
if (unlikely((global.mode & MODE_DEBUG) &&
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
int len;
int max_accept = global.tune.maxaccept;
int cfd;
int ret;
+ int loops = 0;
if (unlikely(l->nbconn >= l->maxconn)) {
listener_full(l);
struct sockaddr_storage addr;
socklen_t laddr = sizeof(addr);
+ loops++;
cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
if (unlikely(cfd == -1)) {
switch (errno) {
send_log(p, LOG_EMERG,
"Proxy %s reached system FD limit at %d. Please check system tunables.\n",
p->id, maxfd);
- if (l->nbconn)
- listener_full(l);
+ limit_listener(l, &global_listener_queue);
return 0;
case EMFILE:
if (p)
send_log(p, LOG_EMERG,
"Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
p->id, maxfd);
- if (l->nbconn)
- listener_full(l);
+ limit_listener(l, &global_listener_queue);
return 0;
case ENOBUFS:
case ENOMEM:
send_log(p, LOG_EMERG,
"Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
p->id, maxfd);
- if (l->nbconn)
- listener_full(l);
+ limit_listener(l, &global_listener_queue);
return 0;
default:
return 0;
"Proxy %s reached the configured maximum connection limit. Please check the global 'maxconn' value.\n",
p->id);
close(cfd);
+ limit_listener(l, &global_listener_queue);
return 0;
}
if (ret == 0) /* successful termination */
continue;
- if (p) {
- disable_listener(l);
- p->state = PR_STIDLE;
- }
+ limit_listener(l, &global_listener_queue);
return 0;
}
}
} /* end of while (p->feconn < p->maxconn) */
+
+ /* if we did not even enter the loop, we've reached resource limits */
+ if (!loops && max_accept)
+ limit_listener(l, &global_listener_queue);
+
return 0;
}