mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Merge branch 'evhttp-request-own-fixes'
I hope that I validated all places where evhttp_request_free() called and ownership of request can be belong to user-specific code. * evhttp-request-own-fixes: http: fix evhttp_request_own() by checking EVHTTP_USER_OWNED in more cases test/regress_http: cover evhttp_request_own() Fixes #68
This commit is contained in:
commit
9b16d9b845
30
http.c
30
http.c
@ -681,11 +681,21 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free connection ownership of which can be acquired by user using
|
||||||
|
* evhttp_request_own(). */
|
||||||
|
static inline void
|
||||||
|
evhttp_request_free_auto(struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
if (!(req->flags & EVHTTP_USER_OWNED)) {
|
||||||
|
evhttp_request_free(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
|
evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when evcon has experienced a (non-recoverable? -NM) error, as
|
/* Called when evcon has experienced a (non-recoverable? -NM) error, as
|
||||||
@ -829,11 +839,9 @@ evhttp_connection_done(struct evhttp_connection *evcon)
|
|||||||
/* notify the user of the request */
|
/* notify the user of the request */
|
||||||
(*req->cb)(req, req->cb_arg);
|
(*req->cb)(req, req->cb_arg);
|
||||||
|
|
||||||
/* if this was an outgoing request, we own and it's done. so free it.
|
/* if this was an outgoing request, we own and it's done. so free it. */
|
||||||
* unless the callback specifically requested to own the request.
|
if (con_outgoing) {
|
||||||
*/
|
evhttp_request_free_auto(req);
|
||||||
if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
|
|
||||||
evhttp_request_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this was the last request of an outgoing connection and we're
|
/* If this was the last request of an outgoing connection and we're
|
||||||
@ -993,7 +1001,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
return;
|
return;
|
||||||
case REQUEST_CANCELED:
|
case REQUEST_CANCELED:
|
||||||
/* request canceled */
|
/* request canceled */
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return;
|
return;
|
||||||
case MORE_DATA_EXPECTED:
|
case MORE_DATA_EXPECTED:
|
||||||
default:
|
default:
|
||||||
@ -1039,7 +1047,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
evbuffer_drain(req->input_buffer,
|
evbuffer_drain(req->input_buffer,
|
||||||
evbuffer_get_length(req->input_buffer));
|
evbuffer_get_length(req->input_buffer));
|
||||||
if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
|
if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1356,7 +1364,7 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
|
|||||||
|
|
||||||
/* we might want to set an error here */
|
/* we might want to set an error here */
|
||||||
request->cb(request, request->cb_arg);
|
request->cb(request, request->cb_arg);
|
||||||
evhttp_request_free(request);
|
evhttp_request_free_auto(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2514,7 +2522,7 @@ evhttp_make_request(struct evhttp_connection *evcon,
|
|||||||
mm_free(req->uri);
|
mm_free(req->uri);
|
||||||
if ((req->uri = mm_strdup(uri)) == NULL) {
|
if ((req->uri = mm_strdup(uri)) == NULL) {
|
||||||
event_warn("%s: strdup", __func__);
|
event_warn("%s: strdup", __func__);
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2577,7 +2585,7 @@ evhttp_cancel_request(struct evhttp_request *req)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -971,6 +971,7 @@ http_allowed_methods_test(void *arg)
|
|||||||
evutil_closesocket(fd3);
|
evutil_closesocket(fd3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void http_request_no_action_done(struct evhttp_request *, void *);
|
||||||
static void http_request_done(struct evhttp_request *, void *);
|
static void http_request_done(struct evhttp_request *, void *);
|
||||||
static void http_request_empty_done(struct evhttp_request *, void *);
|
static void http_request_empty_done(struct evhttp_request *, void *);
|
||||||
|
|
||||||
@ -1334,6 +1335,13 @@ http_cancel_test(void *arg)
|
|||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_request_no_action_done(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
EVUTIL_ASSERT(exit_base);
|
||||||
|
event_base_loopexit(exit_base, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_request_done(struct evhttp_request *req, void *arg)
|
http_request_done(struct evhttp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
@ -4055,6 +4063,41 @@ http_write_during_read_test(void *arg)
|
|||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_request_own_test(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
ev_uint16_t port = 0;
|
||||||
|
struct evhttp_connection *evcon = NULL;
|
||||||
|
struct evhttp_request *req = NULL;
|
||||||
|
|
||||||
|
test_ok = 0;
|
||||||
|
exit_base = data->base;
|
||||||
|
|
||||||
|
http = http_setup(&port, data->base, 0);
|
||||||
|
evhttp_free(http);
|
||||||
|
|
||||||
|
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
|
||||||
|
tt_assert(evcon);
|
||||||
|
|
||||||
|
req = evhttp_request_new(http_request_no_action_done, NULL);
|
||||||
|
|
||||||
|
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
|
||||||
|
tt_abort_msg("Couldn't make request");
|
||||||
|
}
|
||||||
|
evhttp_request_own(req);
|
||||||
|
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (evcon)
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
if (req)
|
||||||
|
evhttp_request_free(req);
|
||||||
|
|
||||||
|
test_ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define HTTP_LEGACY(name) \
|
#define HTTP_LEGACY(name) \
|
||||||
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
|
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
|
||||||
http_##name##_test }
|
http_##name##_test }
|
||||||
@ -4116,6 +4159,7 @@ struct testcase_t http_testcases[] = {
|
|||||||
HTTP(set_family_ipv6),
|
HTTP(set_family_ipv6),
|
||||||
|
|
||||||
HTTP(write_during_read),
|
HTTP(write_during_read),
|
||||||
|
HTTP(request_own),
|
||||||
|
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user