From ebcf5efcfe208ee4381ac6d5ed6783b77fbd6056 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Fri, 19 Dec 2008 22:42:51 +0000 Subject: [PATCH] fix memory leaks in the regression tools; add another close detection test that validates that there are no dangling connections on the server svn:r969 --- test/regress.c | 11 ++++++++ test/regress_http.c | 61 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/test/regress.c b/test/regress.c index a1949864..9ba8c049 100644 --- a/test/regress.c +++ b/test/regress.c @@ -827,6 +827,7 @@ test_free_active_base(void) event_base_free(base1); test_ok = 1; cleanup_test(); + event_base_free(global_base); global_base = event_init(); } @@ -1259,6 +1260,7 @@ test_evbuffer_readln(void) cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); if (cp) goto done; + free(cp); evbuffer_validate(evb); evbuffer_add(evb, "\n", 1); evbuffer_validate(evb); @@ -1266,6 +1268,7 @@ test_evbuffer_readln(void) cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); if (!cp || sz != strlen(cp) || strcmp(cp, "More")) goto done; + free(cp); if (EVBUFFER_LENGTH(evb) != 0) goto done; evbuffer_validate(evb); @@ -1290,11 +1293,13 @@ test_evbuffer_readln(void) cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); if (cp) goto done; + free(cp); evbuffer_add(evb, "\n", 1); evbuffer_validate(evb); cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); if (!cp || sz != strlen(cp) || strcmp(cp, "Text")) goto done; + free(cp); evbuffer_validate(evb); /* Test CRLF_STRICT - across boundaries*/ @@ -1330,12 +1335,14 @@ test_evbuffer_readln(void) cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); if (cp) goto done; + free(cp); evbuffer_validate(evb); evbuffer_add(evb, "\n", 1); evbuffer_validate(evb); cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); if (!cp || sz != strlen(cp) || strcmp(cp, "More")) goto done; + free(cp); cp = NULL; evbuffer_validate(evb); if (EVBUFFER_LENGTH(evb) != 0) goto done; @@ -2258,6 +2265,10 @@ main (int argc, char **argv) err = WSAStartup( wVersionRequested, &wsaData ); #endif +#ifndef WIN32 + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + return (1); +#endif setvbuf(stdout, NULL, _IONBF, 0); test_methods(); diff --git a/test/regress_http.c b/test/regress_http.c index afb0e1d9..a9056488 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -74,6 +74,7 @@ static void http_post_cb(struct evhttp_request *req, void *arg); static void http_put_cb(struct evhttp_request *req, void *arg); static void http_delete_cb(struct evhttp_request *req, void *arg); static void http_delay_cb(struct evhttp_request *req, void *arg); +static void http_large_delay_cb(struct evhttp_request *req, void *arg); static void http_dispatcher_cb(struct evhttp_request *req, void *arg); static struct evhttp * @@ -103,6 +104,7 @@ http_setup(short *pport, struct event_base *base) evhttp_set_cb(myhttp, "/putit", http_put_cb, NULL); evhttp_set_cb(myhttp, "/deleteit", http_delete_cb, NULL); evhttp_set_cb(myhttp, "/delay", http_delay_cb, NULL); + evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, NULL); evhttp_set_cb(myhttp, "/", http_dispatcher_cb, NULL); *pport = port; @@ -277,7 +279,7 @@ http_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg) struct chunk_req_state *state = arg; struct timeval when = { 0, 0 }; - evbuffer_add_printf(evb, CHUNKS[state->i]); + evbuffer_add_printf(evb, "%s", CHUNKS[state->i]); evhttp_send_reply_chunk(state->req, evb); evbuffer_free(evb); @@ -419,6 +421,19 @@ http_delay_cb(struct evhttp_request *req, void *arg) event_once(-1, EV_TIMEOUT, http_delay_reply, req, &tv); } +static struct evhttp_connection *delayed_client; + +static void +http_large_delay_cb(struct evhttp_request *req, void *arg) +{ + struct timeval tv; + timerclear(&tv); + tv.tv_sec = 3; + + event_once(-1, EV_TIMEOUT, http_delay_reply, req, &tv); + evhttp_connection_fail(delayed_client, EVCON_HTTP_EOF); +} + /* * HTTP DELETE test, just piggyback on the basic test */ @@ -1293,14 +1308,17 @@ http_failure_test(void) static void close_detect_done(struct evhttp_request *req, void *arg) { + struct timeval tv; if (req == NULL || req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); exit(1); } test_ok = 1; - event_loopexit(NULL); + + timerclear(&tv); + tv.tv_sec = 3; + event_loopexit(&tv); } static void @@ -1327,7 +1345,7 @@ close_detect_cb(struct evhttp_request *req, void *arg) struct evhttp_connection *evcon = arg; struct timeval tv; - if (req->response_code != HTTP_OK) { + if (req != NULL && req->response_code != HTTP_OK) { fprintf(stderr, "FAILED\n"); exit(1); @@ -1336,20 +1354,21 @@ close_detect_cb(struct evhttp_request *req, void *arg) timerclear(&tv); tv.tv_sec = 3; /* longer than the http time out */ - /* launch a new request on the persistent connection in 6 seconds */ + /* launch a new request on the persistent connection in 3 seconds */ event_once(-1, EV_TIMEOUT, close_detect_launch, evcon, &tv); } static void -http_close_detection(void) +http_close_detection(int with_delay) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; - fprintf(stdout, "Testing Connection Close Detection: "); + fprintf(stdout, "Testing Connection Close Detection%s: ", + with_delay ? " (with delay)" : ""); http = http_setup(&port, NULL); @@ -1362,6 +1381,8 @@ http_close_detection(void) exit(1); } + delayed_client = evcon; + /* * At this point, we want to schedule a request to the HTTP * server using our make request method. @@ -1373,7 +1394,8 @@ http_close_detection(void) evhttp_add_header(req->output_headers, "Host", "somehost"); /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + if (evhttp_make_request(evcon, + req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } @@ -1385,6 +1407,12 @@ http_close_detection(void) exit(1); } + /* at this point, the http server should have no connection */ + if (TAILQ_FIRST(&http->connections) != NULL) { + fprintf(stdout, "FAILED (left connections)\n"); + exit(1); + } + evhttp_connection_free(evcon); evhttp_free(http); @@ -1449,7 +1477,8 @@ fail: static void http_base_test(void) { - struct bufferevent *bev; + struct event_base *tmp; + struct bufferevent *bev; int fd; const char *http_request; short port = -1; @@ -1463,7 +1492,7 @@ http_base_test(void) * create another bogus base - which is being used by all subsequen * tests - yuck! */ - event_init(); + tmp = event_init(); http = http_setup(&port, base); @@ -1490,7 +1519,7 @@ http_base_test(void) evhttp_free(http); event_base_free(base); - base = NULL; + base = tmp; if (test_ok != 2) { fprintf(stdout, "FAILED\n"); @@ -1576,8 +1605,8 @@ http_incomplete_test(int use_timeout) evutil_gettimeofday(&tv_end, NULL); evutil_timersub(&tv_end, &tv_start, &tv_end); + bufferevent_free(bev); if (use_timeout) { - bufferevent_free(bev); EVUTIL_CLOSESOCKET(fd); } @@ -1692,6 +1721,8 @@ http_chunked_errorcb(struct bufferevent *bev, short what, void *arg) free((char *)header); test_ok = 2; + + evhttp_request_free(req); } out: @@ -1774,6 +1805,8 @@ http_chunk_out_test(void) event_dispatch(); + bufferevent_free(bev); + evutil_gettimeofday(&tv_end, NULL); evutil_timersub(&tv_end, &tv_start, &tv_end); @@ -2312,6 +2345,7 @@ http_negative_content_length_test(void) event_dispatch(); + evhttp_connection_free(evcon); evhttp_free(http); if (test_ok != 1) { @@ -2334,7 +2368,8 @@ http_suite(void) http_connection_test(0 /* not-persistent */); http_connection_test(1 /* persistent */); http_virtual_host_test(); - http_close_detection(); + http_close_detection(0 /* with delay */); + http_close_detection(1 /* with delay */); http_post_test(); http_put_test(); http_delete_test(); -- 2.40.0