Skip to content

Commit

Permalink
lib-http: Clarify http_client_request_*_payload() API and minor chang…
Browse files Browse the repository at this point in the history
…e to it

The earlier behavior was pretty confusing, and potentially could have caused
double-freeing memory in some situations. Now it's clear that req is set to NULL
always when the request is finished, regardless of whether it has any references left.

Changed http_client_request_finish_payload() to return 0 on success instead of 1.
This could have been left alone, but it's unlikely that there is any code outside
Dovecot core that calls it and this way is cleaner.
  • Loading branch information
sirainen committed Feb 22, 2016
1 parent d1f964d commit c3a4c93
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
20 changes: 18 additions & 2 deletions src/lib-http/http-client-request.c
Expand Up @@ -711,14 +711,30 @@ http_client_request_continue_payload(struct http_client_request **_req,
int http_client_request_send_payload(struct http_client_request **_req,
const unsigned char *data, size_t size)
{
struct http_client_request *req = *_req;
int ret;

i_assert(data != NULL);

return http_client_request_continue_payload(_req, data, size);
ret = http_client_request_continue_payload(&req, data, size);
if (ret < 0)
*_req = NULL;
else {
i_assert(ret == 0);
i_assert(req != NULL);
}
return ret;
}

int http_client_request_finish_payload(struct http_client_request **_req)
{
return http_client_request_continue_payload(_req, NULL, 0);
struct http_client_request *req = *_req;
int ret;

*_req = NULL;
ret = http_client_request_continue_payload(&req, NULL, 0);
i_assert(ret != 0);
return ret < 0 ? -1 : 0;
}

static void http_client_request_payload_input(struct http_client_request *req)
Expand Down
6 changes: 5 additions & 1 deletion src/lib-http/http-client.h
Expand Up @@ -236,9 +236,13 @@ void http_client_request_set_destroy_callback(struct http_client_request *req,

/* submits request and blocks until provided payload is sent. Multiple calls
are allowed; payload transmission is ended with
http_client_request_finish_payload(). */
http_client_request_finish_payload(). If the sending fails, returns -1
and sets req=NULL to indicate that the request was freed, otherwise
returns 0 and req is unchanged. */
int http_client_request_send_payload(struct http_client_request **req,
const unsigned char *data, size_t size);
/* Finish sending the payload. Always frees req and sets it to NULL.
Returns 0 on success, -1 on error. */
int http_client_request_finish_payload(struct http_client_request **req);

void http_client_request_start_tunnel(struct http_client_request *req,
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/fts-solr/solr-connection.c
Expand Up @@ -532,7 +532,7 @@ int solr_connection_post_end(struct solr_connection_post **_post)
*_post = NULL;

if (!post->failed) {
if (http_client_request_finish_payload(&post->http_req) <= 0 ||
if (http_client_request_finish_payload(&post->http_req) < 0 ||
conn->request_status < 0) {
ret = -1;
}
Expand Down

0 comments on commit c3a4c93

Please sign in to comment.