nginx

view src/http/modules/ngx_http_stub_status_module.c @ 5876:973fded4f461

Gzip, gunzip: flush busy buffers if any. Previous code resulted in transfer stalls when client happened to read all the data in buffers at once, while all gzip buffers were exhausted (but ctx->nomem wasn't set). Make sure to call next body filter at least once per call if there are busy buffers. Additionally, handling of calls with NULL chain was changed to follow the same logic, i.e., next body filter is only called with NULL chain if there are busy buffers. This is expected to fix "output chain is empty" alerts as reported by some users after c52a761a2029 (1.5.7).
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 15 Oct 2014 22:57:23 +0400
parents dc7c139fca21
children
line source
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
13 static ngx_int_t ngx_http_stub_status_handler(ngx_http_request_t *r);
14 static ngx_int_t ngx_http_stub_status_variable(ngx_http_request_t *r,
15 ngx_http_variable_value_t *v, uintptr_t data);
16 static ngx_int_t ngx_http_stub_status_add_variables(ngx_conf_t *cf);
17 static char *ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd,
18 void *conf);
21 static ngx_command_t ngx_http_status_commands[] = {
23 { ngx_string("stub_status"),
24 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
25 ngx_http_set_stub_status,
26 0,
27 0,
28 NULL },
30 ngx_null_command
31 };
34 static ngx_http_module_t ngx_http_stub_status_module_ctx = {
35 ngx_http_stub_status_add_variables, /* preconfiguration */
36 NULL, /* postconfiguration */
38 NULL, /* create main configuration */
39 NULL, /* init main configuration */
41 NULL, /* create server configuration */
42 NULL, /* merge server configuration */
44 NULL, /* create location configuration */
45 NULL /* merge location configuration */
46 };
49 ngx_module_t ngx_http_stub_status_module = {
50 NGX_MODULE_V1,
51 &ngx_http_stub_status_module_ctx, /* module context */
52 ngx_http_status_commands, /* module directives */
53 NGX_HTTP_MODULE, /* module type */
54 NULL, /* init master */
55 NULL, /* init module */
56 NULL, /* init process */
57 NULL, /* init thread */
58 NULL, /* exit thread */
59 NULL, /* exit process */
60 NULL, /* exit master */
61 NGX_MODULE_V1_PADDING
62 };
65 static ngx_http_variable_t ngx_http_stub_status_vars[] = {
67 { ngx_string("connections_active"), NULL, ngx_http_stub_status_variable,
68 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
70 { ngx_string("connections_reading"), NULL, ngx_http_stub_status_variable,
71 1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
73 { ngx_string("connections_writing"), NULL, ngx_http_stub_status_variable,
74 2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
76 { ngx_string("connections_waiting"), NULL, ngx_http_stub_status_variable,
77 3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
79 { ngx_null_string, NULL, NULL, 0, 0, 0 }
80 };
83 static ngx_int_t
84 ngx_http_stub_status_handler(ngx_http_request_t *r)
85 {
86 size_t size;
87 ngx_int_t rc;
88 ngx_buf_t *b;
89 ngx_chain_t out;
90 ngx_atomic_int_t ap, hn, ac, rq, rd, wr, wa;
92 if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
93 return NGX_HTTP_NOT_ALLOWED;
94 }
96 rc = ngx_http_discard_request_body(r);
98 if (rc != NGX_OK) {
99 return rc;
100 }
102 r->headers_out.content_type_len = sizeof("text/plain") - 1;
103 ngx_str_set(&r->headers_out.content_type, "text/plain");
104 r->headers_out.content_type_lowcase = NULL;
106 if (r->method == NGX_HTTP_HEAD) {
107 r->headers_out.status = NGX_HTTP_OK;
109 rc = ngx_http_send_header(r);
111 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
112 return rc;
113 }
114 }
116 size = sizeof("Active connections: \n") + NGX_ATOMIC_T_LEN
117 + sizeof("server accepts handled requests\n") - 1
118 + 6 + 3 * NGX_ATOMIC_T_LEN
119 + sizeof("Reading: Writing: Waiting: \n") + 3 * NGX_ATOMIC_T_LEN;
121 b = ngx_create_temp_buf(r->pool, size);
122 if (b == NULL) {
123 return NGX_HTTP_INTERNAL_SERVER_ERROR;
124 }
126 out.buf = b;
127 out.next = NULL;
129 ap = *ngx_stat_accepted;
130 hn = *ngx_stat_handled;
131 ac = *ngx_stat_active;
132 rq = *ngx_stat_requests;
133 rd = *ngx_stat_reading;
134 wr = *ngx_stat_writing;
135 wa = *ngx_stat_waiting;
137 b->last = ngx_sprintf(b->last, "Active connections: %uA \n", ac);
139 b->last = ngx_cpymem(b->last, "server accepts handled requests\n",
140 sizeof("server accepts handled requests\n") - 1);
142 b->last = ngx_sprintf(b->last, " %uA %uA %uA \n", ap, hn, rq);
144 b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA \n",
145 rd, wr, wa);
147 r->headers_out.status = NGX_HTTP_OK;
148 r->headers_out.content_length_n = b->last - b->pos;
150 b->last_buf = (r == r->main) ? 1 : 0;
151 b->last_in_chain = 1;
153 rc = ngx_http_send_header(r);
155 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
156 return rc;
157 }
159 return ngx_http_output_filter(r, &out);
160 }
163 static ngx_int_t
164 ngx_http_stub_status_variable(ngx_http_request_t *r,
165 ngx_http_variable_value_t *v, uintptr_t data)
166 {
167 u_char *p;
168 ngx_atomic_int_t value;
170 p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
171 if (p == NULL) {
172 return NGX_ERROR;
173 }
175 switch (data) {
176 case 0:
177 value = *ngx_stat_active;
178 break;
180 case 1:
181 value = *ngx_stat_reading;
182 break;
184 case 2:
185 value = *ngx_stat_writing;
186 break;
188 case 3:
189 value = *ngx_stat_waiting;
190 break;
192 /* suppress warning */
193 default:
194 value = 0;
195 break;
196 }
198 v->len = ngx_sprintf(p, "%uA", value) - p;
199 v->valid = 1;
200 v->no_cacheable = 0;
201 v->not_found = 0;
202 v->data = p;
204 return NGX_OK;
205 }
208 static ngx_int_t
209 ngx_http_stub_status_add_variables(ngx_conf_t *cf)
210 {
211 ngx_http_variable_t *var, *v;
213 for (v = ngx_http_stub_status_vars; v->name.len; v++) {
214 var = ngx_http_add_variable(cf, &v->name, v->flags);
215 if (var == NULL) {
216 return NGX_ERROR;
217 }
219 var->get_handler = v->get_handler;
220 var->data = v->data;
221 }
223 return NGX_OK;
224 }
227 static char *
228 ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
229 {
230 ngx_http_core_loc_conf_t *clcf;
232 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
233 clcf->handler = ngx_http_stub_status_handler;
235 return NGX_CONF_OK;
236 }