Skip to content

Commit cc2a7fb

Browse files
author
mdounin
committed
Accept moderation in case of EMFILE/ENFILE.
In case of EMFILE/ENFILE returned from accept() we disable accept events, and (in case of no accept mutex used) arm timer to re-enable them later. With accept mutex we just drop it, and rely on normal accept mutex handling to re-enable accept events once it's acquired again. As we now handle errors in question, logging level was changed to "crit" (instead of "alert" used for unknown errors). Note: the code might call ngx_enable_accept_events() multiple times if there are many listen sockets. The ngx_enable_accept_events() function was modified to check if connection is already active (via c->read->active) and skip it then, thus making multiple calls safe. git-svn-id: svn://svn.nginx.org/nginx/trunk@4619 73f98a42-aea0-e011-b76d-00259023448c
1 parent 1129a2e commit cc2a7fb

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

Diff for: src/event/ngx_event_accept.c

+44-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ ngx_event_accept(ngx_event_t *ev)
2121
socklen_t socklen;
2222
ngx_err_t err;
2323
ngx_log_t *log;
24+
ngx_uint_t level;
2425
ngx_socket_t s;
2526
ngx_event_t *rev, *wev;
2627
ngx_listening_t *ls;
@@ -31,6 +32,14 @@ ngx_event_accept(ngx_event_t *ev)
3132
static ngx_uint_t use_accept4 = 1;
3233
#endif
3334

35+
if (ev->timedout) {
36+
if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
37+
return;
38+
}
39+
40+
ev->timedout = 0;
41+
}
42+
3443
ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
3544

3645
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
@@ -70,10 +79,17 @@ ngx_event_accept(ngx_event_t *ev)
7079
return;
7180
}
7281

82+
level = NGX_LOG_ALERT;
83+
84+
if (err == NGX_ECONNABORTED) {
85+
level = NGX_LOG_ERR;
86+
87+
} else if (err == NGX_EMFILE || err == NGX_ENFILE) {
88+
level = NGX_LOG_CRIT;
89+
}
90+
7391
#if (NGX_HAVE_ACCEPT4)
74-
ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
75-
NGX_LOG_ERR : NGX_LOG_ALERT),
76-
ev->log, err,
92+
ngx_log_error(level, ev->log, err,
7793
use_accept4 ? "accept4() failed" : "accept() failed");
7894

7995
if (use_accept4 && err == NGX_ENOSYS) {
@@ -82,9 +98,7 @@ ngx_event_accept(ngx_event_t *ev)
8298
continue;
8399
}
84100
#else
85-
ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
86-
NGX_LOG_ERR : NGX_LOG_ALERT),
87-
ev->log, err, "accept() failed");
101+
ngx_log_error(level, ev->log, err, "accept() failed");
88102
#endif
89103

90104
if (err == NGX_ECONNABORTED) {
@@ -97,6 +111,26 @@ ngx_event_accept(ngx_event_t *ev)
97111
}
98112
}
99113

114+
if (err == NGX_EMFILE || err == NGX_ENFILE) {
115+
if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
116+
!= NGX_OK)
117+
{
118+
return;
119+
}
120+
121+
if (ngx_use_accept_mutex) {
122+
if (ngx_accept_mutex_held) {
123+
ngx_shmtx_unlock(&ngx_accept_mutex);
124+
ngx_accept_mutex_held = 0;
125+
}
126+
127+
ngx_accept_disabled = 1;
128+
129+
} else {
130+
ngx_add_timer(ev, ecf->accept_mutex_delay);
131+
}
132+
}
133+
100134
return;
101135
}
102136

@@ -383,6 +417,10 @@ ngx_enable_accept_events(ngx_cycle_t *cycle)
383417

384418
c = ls[i].connection;
385419

420+
if (c->read->active) {
421+
continue;
422+
}
423+
386424
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
387425

388426
if (ngx_add_conn(c) == NGX_ERROR) {

Diff for: src/os/unix/ngx_errno.h

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ typedef int ngx_err_t;
2929
#define NGX_ENOTDIR ENOTDIR
3030
#define NGX_EISDIR EISDIR
3131
#define NGX_EINVAL EINVAL
32+
#define NGX_ENFILE ENFILE
33+
#define NGX_EMFILE EMFILE
3234
#define NGX_ENOSPC ENOSPC
3335
#define NGX_EPIPE EPIPE
3436
#define NGX_EINPROGRESS EINPROGRESS

Diff for: src/os/win32/ngx_errno.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ typedef DWORD ngx_err_t;
5454

5555
#define NGX_EALREADY WSAEALREADY
5656
#define NGX_EINVAL WSAEINVAL
57+
#define NGX_EMFILE WSAEMFILE
58+
#define NGX_ENFILE WSAEMFILE
5759

5860

5961
u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);

0 commit comments

Comments
 (0)