Skip to content

Commit 154541b

Browse files
author
Stefan Eissing
committed
v1.0.13 from apache trunk
1 parent 0414b9a commit 154541b

37 files changed

+768
-611
lines changed

Diff for: ChangeLog

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
v1.0.13
2+
--------------------------------------------------------------------------------
3+
* reworked connection state handling. Improved scoreboard update (server-status).
4+
Default on H2KeepAliveTimeout same as H2Timeout, 5 seconds. After that,
5+
connections are closed.
6+
On asynchronous MPMs (event), keep-alive connections no longer block threads,
7+
but exact timeout handling is then up to the MPM. In these MPMs, having a
8+
longer H2KeepAliveTimeout may be suitable.
9+
* new CGI environment variables HTTP2 and H2PUSH. With former "on", the
10+
connection uses HTTP/2. With latter "on", the request may trigger Server Push
11+
via Link headers, as both server and clients support it.
12+
113
v1.0.12
214
--------------------------------------------------------------------------------
315
* alpha release on top of Apache httpd 2.4.18

Diff for: configure.ac

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#
1515

1616
AC_PREREQ([2.69])
17-
AC_INIT([mod_http2], [1.0.12], [[email protected]])
17+
AC_INIT([mod_http2], [1.0.13], [[email protected]])
1818

1919
LT_PREREQ([2.2.6])
2020
LT_INIT()
@@ -122,6 +122,14 @@ HTTPD_VERSION="$($APXS -q HTTPD_VERSION)"
122122
AC_CHECK_LIB([nghttp2], [nghttp2_session_server_new2], ,
123123
[AC_MSG_ERROR("library nghttp2 not found")])
124124

125+
AC_CHECK_HEADERS([nghttp2/nghttp2.h])
126+
# nghttp2 >= 1.3.0: access to stream weights
127+
AC_CHECK_FUNCS([nghttp2_stream_get_weight],
128+
[CPPFLAGS="$CPPFLAGS -DH2_NG2_STREAM_API"], [])
129+
# nghttp2 >= 1.5.0: changing stream priorities
130+
AC_CHECK_FUNCS([nghttp2_session_change_stream_priority],
131+
[CPPFLAGS="$CPPFLAGS -DH2_NG2_CHANGE_PRIO"], [])
132+
125133
# Checks for header files.
126134
AC_CHECK_HEADERS([ \
127135
assert.h \

Diff for: mod_http2/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
*.lo
44
*.la
55
.libs
6+
h2_version.h
67
Makefile.in
78
Makefile

Diff for: mod_http2/h2_config.c

+2-11
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,11 @@ static h2_config defconf = {
6060
1, /* HTTP/2 server push enabled */
6161
NULL, /* map of content-type to priorities */
6262
5, /* normal connection timeout */
63-
5*60, /* idle connection timeout */
64-
2*60, /* stream timeout */
63+
5, /* keepalive timeout */
64+
0, /* stream timeout */
6565
};
6666

6767
static int files_per_session;
68-
static int async_mpm;
6968

7069
void h2_config_init(apr_pool_t *pool)
7170
{
@@ -90,14 +89,6 @@ void h2_config_init(apr_pool_t *pool)
9089
/* don't know anything about it, stay safe */
9190
break;
9291
}
93-
if (ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm) != APR_SUCCESS) {
94-
async_mpm = 0;
95-
}
96-
}
97-
98-
int h2_config_async_mpm(void)
99-
{
100-
return async_mpm;
10192
}
10293

10394
static void *h2_config_create(apr_pool_t *pool,

Diff for: mod_http2/h2_config.h

-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,5 @@ void h2_config_init(apr_pool_t *pool);
9595
const struct h2_priority *h2_config_get_priority(const h2_config *conf,
9696
const char *content_type);
9797

98-
int h2_config_async_mpm(void);
99-
10098
#endif /* __mod_h2__h2_config_h__ */
10199

Diff for: mod_http2/h2_conn.c

+43-39
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,31 @@ static struct h2_workers *workers;
4343

4444
static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN;
4545
static module *mpm_module;
46-
static int checked;
46+
static int async_mpm;
4747

48-
static void check_modules(void)
48+
static void check_modules(int force)
4949
{
50+
static int checked = 0;
5051
int i;
51-
if (!checked) {
52+
53+
if (force || !checked) {
5254
for (i = 0; ap_loaded_modules[i]; ++i) {
5355
module *m = ap_loaded_modules[i];
56+
5457
if (!strcmp("event.c", m->name)) {
5558
mpm_type = H2_MPM_EVENT;
5659
mpm_module = m;
60+
break;
5761
}
5862
else if (!strcmp("worker.c", m->name)) {
5963
mpm_type = H2_MPM_WORKER;
6064
mpm_module = m;
65+
break;
6166
}
6267
else if (!strcmp("prefork.c", m->name)) {
6368
mpm_type = H2_MPM_PREFORK;
6469
mpm_module = m;
70+
break;
6571
}
6672
}
6773
checked = 1;
@@ -72,40 +78,34 @@ apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s)
7278
{
7379
const h2_config *config = h2_config_sget(s);
7480
apr_status_t status = APR_SUCCESS;
75-
int minw = h2_config_geti(config, H2_CONF_MIN_WORKERS);
76-
int maxw = h2_config_geti(config, H2_CONF_MAX_WORKERS);
81+
int minw, maxw;
7782
int max_threads_per_child = 0;
7883
int idle_secs = 0;
79-
int i;
8084

81-
h2_config_init(pool);
85+
check_modules(1);
8286

8387
ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
8488

85-
for (i = 0; ap_loaded_modules[i]; ++i) {
86-
module *m = ap_loaded_modules[i];
87-
if (!strcmp("event.c", m->name)) {
88-
mpm_type = H2_MPM_EVENT;
89-
mpm_module = m;
90-
}
91-
else if (!strcmp("worker.c", m->name)) {
92-
mpm_type = H2_MPM_WORKER;
93-
mpm_module = m;
94-
}
95-
else if (!strcmp("prefork.c", m->name)) {
96-
mpm_type = H2_MPM_PREFORK;
97-
mpm_module = m;
98-
}
89+
status = ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm);
90+
if (status != APR_SUCCESS) {
91+
ap_log_error(APLOG_MARK, APLOG_TRACE1, status, s, "querying MPM for async");
92+
/* some MPMs do not implemnent this */
93+
async_mpm = 0;
94+
status = APR_SUCCESS;
9995
}
96+
97+
h2_config_init(pool);
10098

99+
minw = h2_config_geti(config, H2_CONF_MIN_WORKERS);
100+
maxw = h2_config_geti(config, H2_CONF_MAX_WORKERS);
101101
if (minw <= 0) {
102102
minw = max_threads_per_child;
103103
}
104104
if (maxw <= 0) {
105105
maxw = minw;
106106
}
107107

108-
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
108+
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
109109
"h2_workers: min=%d max=%d, mthrpchild=%d",
110110
minw, maxw, max_threads_per_child);
111111

@@ -119,21 +119,22 @@ apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s)
119119
return status;
120120
}
121121

122-
h2_mpm_type_t h2_conn_mpm_type(void) {
123-
check_modules();
122+
h2_mpm_type_t h2_conn_mpm_type(void)
123+
{
124+
check_modules(0);
124125
return mpm_type;
125126
}
126127

127-
static module *h2_conn_mpm_module(void) {
128-
check_modules();
128+
static module *h2_conn_mpm_module(void)
129+
{
130+
check_modules(0);
129131
return mpm_module;
130132
}
131133

132134
apr_status_t h2_conn_setup(h2_ctx *ctx, conn_rec *c, request_rec *r)
133135
{
134136
h2_session *session;
135137

136-
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "setup");
137138
if (!workers) {
138139
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02911)
139140
"workers not initialized");
@@ -154,45 +155,48 @@ apr_status_t h2_conn_setup(h2_ctx *ctx, conn_rec *c, request_rec *r)
154155
return APR_SUCCESS;
155156
}
156157

157-
apr_status_t h2_conn_process(h2_ctx *ctx, int async)
158+
static apr_status_t h2_conn_process(h2_ctx *ctx)
158159
{
159-
apr_status_t status;
160160
h2_session *session;
161161

162162
session = h2_ctx_session_get(ctx);
163163
if (session->c->cs) {
164164
session->c->cs->sense = CONN_SENSE_DEFAULT;
165165
}
166166

167-
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "process");
168-
status = h2_session_process(session, async);
167+
h2_session_process(session, async_mpm);
169168

169+
session->c->keepalive = AP_CONN_KEEPALIVE;
170170
if (session->c->cs) {
171171
session->c->cs->state = CONN_STATE_WRITE_COMPLETION;
172172
}
173173

174-
if (status == APR_EOF) {
175-
ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
174+
if (session->state == H2_SESSION_ST_CLOSING) {
175+
ap_log_cerror( APLOG_MARK, APLOG_DEBUG, 0, session->c,
176176
"h2_session(%ld): done", session->id);
177177
/* Make sure this connection gets closed properly. */
178178
ap_update_child_status_from_conn(session->c->sbh, SERVER_CLOSING, session->c);
179179
session->c->keepalive = AP_CONN_CLOSE;
180180

181181
h2_session_close(session);
182-
/* hereafter session will be gone */
183-
}
184-
else {
185-
session->c->keepalive = AP_CONN_KEEPALIVE;
182+
/* hereafter session may be gone */
186183
}
187184

188185
return DONE;
189186
}
190187

191188
apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c)
192189
{
190+
int mpm_state = 0;
193191
do {
194-
h2_conn_process(ctx, 0);
195-
} while (c->keepalive == AP_CONN_KEEPALIVE && !c->aborted);
192+
h2_conn_process(ctx);
193+
194+
if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state)) {
195+
break;
196+
}
197+
} while (!async_mpm
198+
&& c->keepalive == AP_CONN_KEEPALIVE
199+
&& mpm_state != AP_MPMQ_STOPPING);
196200

197201
return DONE;
198202
}

Diff for: mod_http2/h2_conn.h

-10
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,6 @@ struct h2_task;
2828
*/
2929
apr_status_t h2_conn_setup(struct h2_ctx *ctx, conn_rec *c, request_rec *r);
3030

31-
/**
32-
* Process the HTTP/2 connection. Return whenever blocking reads or
33-
* long writes have to be performed.
34-
*
35-
* @param ctx the http2 context to process
36-
* @return APR_SUCCESS as long as processing needs to continue, APR_EOF
37-
* when HTTP/2 session is done.
38-
*/
39-
apr_status_t h2_conn_process(struct h2_ctx *ctx, int async);
40-
4131
/**
4232
* Run the HTTP/2 connection in synchronous fashion.
4333
* Return when the HTTP/2 session is done

Diff for: mod_http2/h2_conn_io.c

+8-22
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c,
7979
}
8080

8181
if (APLOGctrace1(c)) {
82-
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
82+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
8383
"h2_conn_io(%ld): init, buffering=%d, warmup_size=%ld, cd_secs=%f",
8484
io->connection->id, io->buffer_output, (long)io->warmup_size,
8585
((float)io->cooldown_usecs/APR_USEC_PER_SEC));
@@ -106,7 +106,7 @@ static apr_status_t pass_out(apr_bucket_brigade *bb, void *ctx)
106106
ap_update_child_status(io->connection->sbh, SERVER_BUSY_WRITE, NULL);
107107
status = apr_brigade_length(bb, 0, &bblen);
108108
if (status == APR_SUCCESS) {
109-
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
109+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
110110
"h2_conn_io(%ld): pass_out brigade %ld bytes",
111111
io->connection->id, (long)bblen);
112112
status = ap_pass_brigade(io->connection->output_filters, bb);
@@ -135,15 +135,15 @@ static apr_status_t bucketeer_buffer(h2_conn_io *io)
135135
/* long time not written, reset write size */
136136
io->write_size = WRITE_SIZE_INITIAL;
137137
io->bytes_written = 0;
138-
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
138+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
139139
"h2_conn_io(%ld): timeout write size reset to %ld",
140140
(long)io->connection->id, (long)io->write_size);
141141
}
142142
else if (io->write_size < WRITE_SIZE_MAX
143143
&& io->bytes_written >= io->warmup_size) {
144144
/* connection is hot, use max size */
145145
io->write_size = WRITE_SIZE_MAX;
146-
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
146+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
147147
"h2_conn_io(%ld): threshold reached, write size now %ld",
148148
(long)io->connection->id, (long)io->write_size);
149149
}
@@ -172,7 +172,7 @@ apr_status_t h2_conn_io_write(h2_conn_io *io,
172172

173173
io->unflushed = 1;
174174
if (io->bufsize > 0) {
175-
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
175+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
176176
"h2_conn_io: buffering %ld bytes", (long)length);
177177

178178
if (!APR_BRIGADE_EMPTY(io->output)) {
@@ -203,7 +203,7 @@ apr_status_t h2_conn_io_write(h2_conn_io *io,
203203

204204
}
205205
else {
206-
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, io->connection,
206+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, status, io->connection,
207207
"h2_conn_io: writing %ld bytes to brigade", (long)length);
208208
status = apr_brigade_write(io->output, pass_out, io, buf, length);
209209
}
@@ -247,7 +247,7 @@ static apr_status_t h2_conn_io_flush_int(h2_conn_io *io, int force)
247247
if (io->unflushed || force) {
248248
if (io->buflen > 0) {
249249
/* something in the buffer, put it in the output brigade */
250-
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
250+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
251251
"h2_conn_io: flush, flushing %ld bytes", (long)io->buflen);
252252
bucketeer_buffer(io);
253253
io->buflen = 0;
@@ -258,7 +258,7 @@ static apr_status_t h2_conn_io_flush_int(h2_conn_io *io, int force)
258258
apr_bucket_flush_create(io->output->bucket_alloc));
259259
}
260260

261-
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
261+
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, io->connection,
262262
"h2_conn_io: flush");
263263
/* Send it out */
264264
io->unflushed = 0;
@@ -279,17 +279,3 @@ apr_status_t h2_conn_io_pass(h2_conn_io *io)
279279
return h2_conn_io_flush_int(io, 0);
280280
}
281281

282-
apr_status_t h2_conn_io_close(h2_conn_io *io, void *session)
283-
{
284-
apr_bucket *b;
285-
286-
/* Send out anything in our buffers */
287-
h2_conn_io_flush_int(io, 0);
288-
289-
b = h2_bucket_eoc_create(io->connection->bucket_alloc, session);
290-
APR_BRIGADE_INSERT_TAIL(io->output, b);
291-
b = apr_bucket_flush_create(io->connection->bucket_alloc);
292-
APR_BRIGADE_INSERT_TAIL(io->output, b);
293-
return ap_pass_brigade(io->connection->output_filters, io->output);
294-
/* and all is gone */
295-
}

Diff for: mod_http2/h2_conn_io.h

-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,5 @@ apr_status_t h2_conn_io_consider_flush(h2_conn_io *io);
6060

6161
apr_status_t h2_conn_io_pass(h2_conn_io *io);
6262
apr_status_t h2_conn_io_flush(h2_conn_io *io);
63-
apr_status_t h2_conn_io_close(h2_conn_io *io, void *session);
6463

6564
#endif /* defined(__mod_h2__h2_conn_io__) */

0 commit comments

Comments
 (0)